ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

20220728

2022-08-07 21:34:34  阅读:211  来源: 互联网

标签:20220728 int LL tp stk ans mx


一道计算几何的模板题

点很多值域很小,考虑对每个横坐标求出最大/最小的纵坐标,只有这些点可能在凸包上

递推 \(O(p)\) 次后会进入循环节,前面的暴力。之后对于固定的 \(x_i\) 而言,只有前 \(py\) 个对应的 \(y\) 有用。把对应的 \(y\) 集合相同的 \(x_i\) 一起计算,相当于求 RMQ(这部分还是看码比较直观)
时间复杂度线性对数

赛时代码
const int inf = 0x3f3f3f3f;

struct Vec {
	LL x,y; Vec(LL x=0,LL y=0):x(x),y(y){}
	bool operator < (const Vec &a) const { return x!=a.x ? x<a.x : y<a.y; }
	friend bool operator == (const Vec &a,const Vec &b) { return !(a<b||b<a); }
	Vec operator - (const Vec &a) const { return {x-a.x,y-a.y}; }
	LL operator & (const Vec &a) const { return x*a.y-y*a.x; }
};

const int N = 4e5+5;
int n,ax,ay,bx,by,px,py,qx,qy,x[N],y[N],mx[N],mn[N];
LL m;
bool vis[N];
Vec p[N];
int stk[N],tp;

struct {
	int tn,t[N*4];
	void bld(const Vi &p) {
		tn = 1 << __lg(sz(p)+1)+1;
		memset(t,0,sizeof(int)*tn*2);
		Rep(i,0,sz(p)) t[tn+i+1] = y[p[i]];
		rFor(i,tn,1) t[i] = max(t[i<<1],t[i<<1|1]);
	}
	int qry(int l,int r) {
		int res = 0;
		for(l += tn, r += tn+2; l^r^1; l >>= 1, r >>= 1) {
			if( ~l & 1 ) ckmax(res,t[l^1]);
			if( r & 1 ) ckmax(res,t[r^1]);
		}
		return res;
	}
} t1;

struct {
	int tn,t[N*4];
	void bld(const Vi &p) {
		tn = 1 << __lg(sz(p)+1)+1;
		memset(t,0x3f,sizeof(int)*tn*2);
		Rep(i,0,sz(p)) t[tn+i+1] = y[p[i]];
		rFor(i,tn,1) t[i] = min(t[i<<1],t[i<<1|1]);
	}
	int qry(int l,int r) {
		int res = inf;
		for(l += tn, r += tn+2; l^r^1; l >>= 1, r >>= 1) {
			if( ~l & 1 ) ckmin(res,t[l^1]);
			if( r & 1 ) ckmin(res,t[r^1]);
		}
		return res;
	}
} t2;

signed main() {
#ifdef FS
	freopen("geometry2.in","r",stdin); freopen("geometry.out","w",stdout);
#else
	freopen("geometry.in","r",stdin); freopen("geometry.out","w",stdout);
#endif
	memset(mn,0x3f,sizeof mn);
	ios::sync_with_stdio(0);cout.tie(0);
	io>>x[1]>>y[1]>>ax>>ay>>bx>>by>>px>>py>>m;
	int mm = min((LL)2e5,m);
	For(i,2,mm) x[i] = ((LL)ax*x[i-1]+bx) %px, y[i] = ((LL)ay*y[i-1]+by) %py;
	For(i,1,mm) ckmax(mx[x[i]],y[i]), ckmin(mn[x[i]],y[i]);
	m -= mm, x[0] = x[mm], y[0] = y[mm];
	for(int i = 1; ; ++i) {
		x[i] = ((LL)ax*x[i-1]+bx) %px;
		if( x[i] == x[0] ) { qx = i; break; }
	}
	for(int i = 1; ; ++i) {
		y[i] = ((LL)ay*y[i-1]+by) %py;
		if( y[i] == y[0] ) { qy = i; break; }
	}
	Rep(i,0,qy) if( !vis[i] ) {
		Vi p;
		int j = i; do p.pb(j), vis[j] = 1, j = (j+qx)%qy; while( j != i );
		p.insert(p.end(),all(p)), t1.bld(p), t2.bld(p);
		Rep(l,0,sz(p)/2) for(j = p[l]; j < qx; j += qy) {
			if( j > m ) break;
			int r = min(sz(p)-1ll,l+(m-j)/qx);
			ckmax(mx[x[j]],t1.qry(l,r)), ckmin(mn[x[j]],t2.qry(l,r));
		}
	}
	Rep(i,0,px) if( mn[i] < inf ) p[++n] = {i,mx[i]}, p[++n] = {i,mn[i]};
	sort(p+1,p+n+1), n = unique(p+1,p+n+1)-p-1;
	auto push=[&](int i) {
		while( tp > 1 && (p[i]-p[stk[tp-1]] & p[stk[tp]]-p[stk[tp-1]]) > 0 )
			vis[stk[tp--]] = 0;
		vis[i] = 1, stk[++tp] = i;
	};
	memset(vis,0,sizeof vis);
	stk[++tp] = 1; For(i,2,n) push(i); rFor(i,n,1) if( !vis[i] ) push(i);
	LL ans=0; Rep(i,1,tp) ans += p[stk[i]] & p[stk[i+1]];
	cout<<ans;
	return 0;
}

菜肴挑选

不知道如何想到,所以只能生硬的给做法了

  • \(n\) 是奇数:把 \(n\) 个点等距离的放到圆上,枚举所有等腰三角形。这样任意一对点会被作为底边枚举 \(1\) 次,腰枚举 \(2\) 次
  • \(n\) 是偶数:拿前 \(n-1\) 个点做上述过程。猜想最终每条边算了\(6\) 次。可以对前 \(n-1\) 个点中距离为 \(1\) 的点 \(x,y\) 算 \(2\) 次 \((x,y,n)\),距离为 \(2\) 的点 \(x,y\) 算 \(1\) 次 \((x,y,n)\)。此时 \(n\) 与其他点都算了 \(6\) 次,前 \(n-1\) 个点中距离为 \(1\) 的算了 \(5\) 次,距离为 \(2\) 的算了 \(4\) 次,其余算了 \(3\) 次。在枚举所有腰长 \(>1\) 的等腰三角形即可
code
const int N = 1e3+5;
int n,m;
vector<tuple<int,int,int>> ans;

signed main() { freopen("dish.in","r",stdin); freopen("dish.out","w",stdout);
	io>>n, m = n-(~n&1);
	For(i,1,m) For(j,i+1,m)
		if( j-i & 1 ) {
			int k = j + (m-(j-i))/2;
			if( k > m ) k -= m;
			ans.pb(i,j,k);
		} else ans.pb(i,j,i+j>>1);
	if( ~n & 1 ) {
		For(i,1,m) ans.pb(i,i%m+1,n), ans.pb(i,i%m+1,n);
		For(i,1,m) ans.pb(i,(i+1)%m+1,n);
		For(i,1,m) For(j,2,m/2) {
			int x = i-j, y = i+j;
			if( x < 1 ) x += m;
			if( y > m ) y -= m;
			ans.pb(i,x,y);
		}
	}
	io<<sz(ans)<<endl;
	for(auto &i : ans) io<<get<0>(i)<<' '<<get<1>(i)<<' '<<get<2>(i)<<endl;
	return 0;
}

异或矩阵

crashed

对于这种构造方式较简单但数据规模很大的东西可以找一些倍增/递归的性质
打表找规律固然直观,但也不能忽视了宏观的把控

code
LL L,R,mx;
mint ans;

#define mid (l+r>>1)
void dfs(LL l,LL r,bool wh) {
	if( L <= l && r <= R ) {
		auto upd=[](LL x,mint y) {
			if( x > mx ) mx = x, ans = 0;
			if( x == mx ) ans += y;
		};
		int k = __lg(r-l+1); // r-l+1 = pow(2,k)
		upd(r-l,Pow(2,2*k));
		if( !wh ) {
			if( r < R ) upd((r-l)*2+1,2*Pow(2,k)*(R-r));
		} else {
			if( L < l ) upd((r-l)*2+1,2*Pow(2,k)*(l-L));
		}
		return;
	}
	if( L <= mid ) dfs(l,mid,0);
	if( mid < R ) dfs(mid+1,r,1);
}

void MAIN() {
	io>>L>>R;
	dfs(0,(1ll<<60)-1,0);
	io<<mx<<' '<<ans.x<<endl;
} signed main() { freopen("matrix.in","r",stdin); freopen("matrix.out","w",stdout);
	int T=read(); while( T-- ) MAIN(), mx = ans.x = 0;
	return 0;
}

官方题解

写个暴力发现答案是 \(2^{k}-1\)。若答案至少是 \(2^k\),那么存在两个格子分别为 \(2^{k}-1,2^{k}\),分类讨论:

  1. 为 \((x,y),(x+1,y)\):由 \(x\oplus y=2^{k}-1,x+1\oplus y=2^{k}\) 可得 \(x\oplus x+1=2^{k+1}-1\),因此 \(x=A2^{k+1}+2^{k}-1,y=A2^{k+1}\)。存在这样的 \(x,y\) 的限制条件为 \(L\le y<x<R\)。\(L\le A2^{k+1}\le R-2^{k}\Rightarrow L\le R-2^{k}-((R-2^{k})\bmod2^{k+1})\)
  2. 为 \((x,y),(x-1,y)\):同理可得 \(x=A2^{k+1}+2^{k},y=A2^{k+1}+2^{k+1}-1\),\(L+2^{k}\le R-((R+1)\bmod2^{k+1})\)

找到满足条件的最大 \(k\),答案就是 \(2^{k+1}-1\)

计数部分没看懂

标签:20220728,int,LL,tp,stk,ans,mx
来源: https://www.cnblogs.com/401rk8/p/16559922.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有