【考试总结】2022-05-31

亿个社区

fk,n 表示使用 k 个小组覆盖前 n 个住户的最小代价,转移枚举最后一组的起始点即可

不难发现这是斜率优化的形式但是从左往右转移比较麻烦,那么使用分治即可

也就是说 [l,mid] 按照 ti+1 排序建立凸包,待转移的 [mid+1,r] 按照 ti 排序进行弹队头即可

“排序” 都归并复杂度就是 Θ(nklogn)

Code Display
const int N=1e4+10,inf=0x3f3f3f3f3f3f3f3f;
int t[N],X[N],Y[N];
int f[N],g[N],n,K;
vector<int> ordt[N<<2];
inline void build(int p,int l,int r){
	if(l==r) return ;
	int mid=(l+r)>>1;
	build(p<<1,l,mid); build(p<<1|1,mid+1,r);
	rep(i,mid+1,r) ordt[p].emplace_back(i);
	sort(ordt[p].begin(),ordt[p].end(),[&](const int a,const int b){return t[a]<t[b];});
}
int que[N],head,tail;
int id[N],tmp[N];
inline void solve(int p,int l,int r){
	if(l==r) return id[l]=l,void();
	int mid=(l+r)>>1;
	solve(p<<1,l,mid); solve(p<<1|1,mid+1,r);
	auto slope=[&](const int a,const int b){
		if(X[b]==X[a]){
			if(Y[b]>Y[a]) return 1.0*inf;
			else return -1.0*inf;
		}
		return 1.0*(Y[b]-Y[a])/(X[b]-X[a]);
	};
	head=1,tail=0;
	for(int i=l;i<=mid;++i){
		while(tail>head&&slope(que[tail-1],que[tail])>=slope(que[tail],id[i])) --tail;
		que[++tail]=id[i]; 
	}
	for(auto cur:ordt[p]){
		while(tail>head&&slope(que[head],que[head+1])<=2*t[cur]) ++head;
		ckmin(f[cur],Y[que[head]]-X[que[head]]*2*t[cur]+t[cur]*t[cur]);
	}
	int indl=l,indr=mid+1,pos=l-1;
	auto cmp=[&](const int a,const int b){
		return X[a]<X[b]||(X[a]==X[b]&&Y[a]<Y[b]);	
	};
	while(indl<=mid||indr<=r){
		if(indl<=mid&&(indr>r||cmp(id[indl],id[indr]))) tmp[++pos]=id[indl++];
		else tmp[++pos]=id[indr++];
	}
	rep(i,l,r) id[i]=tmp[i];
	return ;
}
signed main(){
	freopen("community.in","r",stdin); freopen("community.out","w",stdout);
	n=read(); K=read();
	for(int i=1;i<=n;++i) t[i]=read(),f[i]=(t[i]-t[1])*(t[i]-t[1]);
	for(int i=0;i<n;++i) X[i]=t[i+1];
	build(1,0,n);
	for(int i=2;i<=K;++i){
		for(int j=1;j<=n;++j) g[j]=f[j],f[j]=inf;
		rep(j,0,i-2) g[j]=inf;
		for(int j=0;j<n;++j) Y[j]=t[j+1]*t[j+1]+g[j];
		solve(1,0,n);
	}
	print(f[n]);
	return 0;
}


亿点整理

问题可以转化成求矩阵 F={Fi,j=[fi,j0]xfi,j} 的积和式在 mod(xK1) 意义下常数项系数是否为 0

目前没有快速求解积和式的方式,但是由于只用判断系数非零所以可以给每个位置额外乘一个随机权值再做行列式

使用拉格朗日插值还原多项式,带入的 x 需要先找个 iK+1 型的质数当做模数,再找到原根 gp1K 次方的 [0,K) 次方

由于只用求常数项系数,所以可以简化取的系数的过程

Code Display
mt19937 Rand((unsigned)time(0));
inline int random(int x){return Rand()%x+1;}
inline int random(int l,int r){return Rand()%(r-l+1)+l;}
int mod;
const int N=110;
int mat[N][N],rnd[N][N],n,K,a[N][N],pw[N][N];
inline bool isprime(int x){for(int i=2;i*i<=x;++i) if(x%i==0) return 0; return 1;}
inline int det(){
	int ans=1;
	for(int i=1;i<=n;++i){
		if(!a[i][i]){
			for(int j=i+1;j<=n;++j) if(a[j][i]){swap(a[j],a[i]); ans=del(0,ans); break;}
		}
		int inv=ksm(a[i][i],mod-2);
		ckmul(ans,a[i][i]);
		for(int j=i+1;j<=n;++j){
			int tmp=mul(inv,a[j][i]);
			for(int k=i;k<=n;++k) ckdel(a[j][k],mul(a[i][k],tmp));
		}
	} 
	return ans;
}
int y[N];
signed main(){
	freopen("sort.in","r",stdin); freopen("sort.out","w",stdout);
	n=read(); K=read();
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j) mat[i][j]=read();		
	}
	for(int i=1e8/K;i;--i) if(isprime(i*K+1)){mod=i*K+1; break;}
	auto get_g=[&](const int p){
		vector<int> fac;
		for(int i=2;i*i<=p-1;++i) if((p-1)%i==0){
			fac.emplace_back(i);
			if(i*i!=p-1) fac.emplace_back((p-1)/i);
		}
		for(int g=2;;++g){
			for(int t:fac) if(ksm(g,t,mod)==1) goto Fail;
			return g;
			Fail:;
		}
	};
	int G=get_g(mod),x=ksm(G,(mod-1)/K,mod);
	int pwx=1;
	for(int i=0;i<K;++i){
		pw[i][0]=1;
		rep(j,1,K-1) pw[i][j]=mul(pw[i][j-1],pwx);
		ckmul(pwx,x);
	}
	while(1.0*clock()/CLOCKS_PER_SEC<2){
		rep(i,1,n) rep(j,1,n) rnd[i][j]=random(0,K-1);
		rep(k,0,K-1){
			rep(i,1,n) rep(j,1,n){
				if(~mat[i][j]) a[i][j]=mul(rnd[i][j],pw[k][mat[i][j]]);
				else a[i][j]=0;
			}
			y[k]=det();
		}
		int sum=0;
		rep(i,0,K-1){
			int coef=1;
			for(int j=0;j<K;++j) if(i!=j) ckmul(coef,mul(mod-pw[j][1],ksm(del(pw[i][1],pw[j][1]),mod-2)));
			ckadd(sum,mul(coef,y[i]));
		}
		if(sum) puts("Yes"),exit(0);
	}
	puts("No");
	return 0;
}


亿块田

使用线段树维护所有操作,直觉上能得到的一个剪枝是如果某个 与操作或者或操作 对整个区间都有效那么可以区间统一做加/减法

具体而言,线段树上维护区间的 And,Or 和以及最大值

对于 And 操作如果一个区间的 OrAnd 全部被当前的操作权值 v 包含那么直接减掉负增量;对于 Or 操作对应的是与操作权值 v 无交

使用势能分析可以发现每次 Or 操作会给 log 个区间的 And 增加 logV 的势能,And 操作会给 Or 操作带来 lognlogV 的势能

那么总复杂度 Θ((n+Q)logVlogn)

Code Display
const int N=2e5+10;
#define ls p<<1
#define rs p<<1|1
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
int a[N],n,Q;
int And[N<<2],Or[N<<2],Mx[N<<2],tag[N<<2];
inline void push_tag(int x,int v){
	tag[x]+=v; Mx[x]+=v; Or[x]+=v; And[x]+=v;
	return ;
}
inline void push_down(int p){
	if(tag[p]){
		push_tag(ls,tag[p]);
		push_tag(rs,tag[p]);
		tag[p]=0;
	}
	return ;
}
inline void push_up(int p){
	Mx[p]=max(Mx[ls],Mx[rs]);
	And[p]=And[ls]&And[rs];
	Or[p]=Or[ls]|Or[rs];
}
inline void push_And(int st,int ed,int v,int p=1,int l=1,int r=n){
	if(st<=l&&r<=ed){
		if((v&(Or[p]-And[p]))==Or[p]-And[p]){
			push_tag(p,(Or[p]&v)-Or[p]);
			return ;
		}
	}
	int mid=(l+r)>>1; push_down(p);
	if(st<=mid) push_And(st,ed,v,lson);
	if(ed>mid) push_And(st,ed,v,rson);
	return push_up(p);
}
inline void push_Or(int st,int ed,int v,int p=1,int l=1,int r=n){
	if(st<=l&&r<=ed){
		if((v&(Or[p]-And[p]))==0){
			push_tag(p,(Or[p]|v)-Or[p]);
			return ;
		}
	}
	int mid=(l+r)>>1; push_down(p);
	if(st<=mid) push_Or(st,ed,v,lson);
	if(ed>mid) push_Or(st,ed,v,rson);
	return push_up(p);
}
inline int query(int st,int ed,int p=1,int l=1,int r=n){
	if(st<=l&&r<=ed) return Mx[p];
	int mid=(l+r)>>1,res=0; push_down(p);
	if(st<=mid) ckmax(res,query(st,ed,lson));
	if(ed>mid) ckmax(res,query(st,ed,rson));
	return res;
}
signed main(){
	freopen("farm.in","r",stdin); freopen("farm.out","w",stdout);
	n=read(); Q=read();
	for(int i=1;i<=n;++i) a[i]=read();
	function<void(int,int,int)>build=[&](int p,int l,int r){
		if(l==r){
			Mx[p]=And[p]=Or[p]=a[l];
			return ;
		}
		int mid=(l+r)>>1;
		build(p<<1,l,mid); build(p<<1|1,mid+1,r);
		return push_up(p);
	};
	build(1,1,n);
	while(Q--){
		int opt=read(),l=read(),r=read();
		if(opt==3){
			print(query(l,r));
		}else{
			int v=read();
			if(opt==1) push_And(l,r,v);
			else push_Or(l,r,v);
		}
	}
	return 0;
}


posted @   没学完四大礼包不改名  阅读(75)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示