欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Codeforces Round #512 (Div. 1) 简要题解

程序员文章站 2022-05-09 22:07:50
...

传送门

Vasya and Triangle

用叉积来计算面积就可以知道最后面积一定是 0.5 的倍数,也就是把kknmnm约分后最后为11或者22。 然后分两种情况讨论即可。

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
} 
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

long long n,m,k,nn,mm; 
int main() {
	cin>>n>>m>>k;
	nn=n; mm=m;
	long long t=__gcd(n,k);
	n/=t; k/=t;
	t=__gcd(m,k);
	m/=t; k/=t;
	if(k>2) {puts("NO"); return 0;}
	puts("YES");
	if(k==2) {cout<<0<<' '<<0<<' '<<n<<' '<<0<<' '<<0<<' '<<m<<'\n';}
	else {
		if(n<nn) n*=2;
		else m*=2;
		cout<<0<<' '<<0<<' '<<n<<' '<<0<<' '<<0<<' '<<m<<'\n';
	}
}

Vasya and Good Sequences

一段区间合法那么sumsum是偶数且maxsum2max \le \frac{sum}{2}。 注意到区间长度大于6464就只与前缀奇偶有关了,可以记两个前缀和。小于暴力枚举。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
} 
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=3e5+50, LIM=150;
int n,a[N],p1[N],p2[N];

int main() {
	cin>>n; p2[0]=1;
	for(int i=1;i<=n;i++) {
		LL x; cin>>x;
		a[i]=__builtin_popcountll(x)+a[i-1];
		if(a[i]&1) ++p1[i]; else ++p2[i];
		p1[i]+=p1[i-1]; p2[i]+=p2[i-1];
	}
	long long ans=0;
	for(int i=1;i<=n;i++) {
		int l=max(1,i-LIM+1);
		if(l!=1) {
			if(a[i]&1) ans+=p1[l-2];
			else ans+=p2[l-2];
		}
		int mx=a[i]-a[i-1];
		for(int j=i;j>=l;j--) {
			if((mx<=(a[i]-a[j-1])/2) && (!((a[i]-a[j-1])&1))) ++ans;
			if(j!=1) mx=max(mx,a[j-1]-a[j-2]);
		}
	} cout<<ans<<'\n';
} 

Putting Boxes Together

容易知道最优点在带权中位数处,线段树+二分。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
} 
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
} 
inline void W(LL x) {
	static int buf[50];
	if(!x) {putchar('0'); return;}
	if(x<0) {putchar('-'); x=-x;}
	while(x) {buf[++buf[0]]=x%10; x/=10;}
	while(buf[0]) {putchar(buf[buf[0]--]+'0');}
}

const int N=2e5+50, mod=1e9+7;
struct node {
	int cnt;
	LL lpos,rpos,s,sl,sr;
	node() {sl=sr=0;} 
} tr[N*4];
int n,q,a[N],w[N];

inline node merge(node L,node R) {
	node t; t.cnt=L.cnt+R.cnt;
	t.lpos=L.lpos; t.rpos=R.rpos;
	t.s=L.s+R.s;
	t.sl=(L.sl+R.sl+(R.rpos-R.cnt-L.rpos)*(L.s%mod))%mod;
	t.sr=(R.sr+L.sr+(R.lpos-L.lpos-L.cnt)*(R.s%mod))%mod;
	return t;
}

inline void build(int k,int l,int r) {
	if(l==r) {
		tr[k].cnt=1;
		tr[k].lpos=tr[k].rpos=a[l];
		tr[k].s=w[l];
		return;
	} int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	tr[k]=merge(tr[k<<1],tr[k<<1|1]);
}
inline void inc(int k,int l,int r,int p) {
	if(l==r) {
		tr[k].cnt=1;
		tr[k].lpos=tr[k].rpos=a[l];
		tr[k].s=w[l];
		return;
	} int mid=(l+r)>>1;
	if(p<=mid) inc(k<<1,l,mid,p);
	else inc(k<<1|1,mid+1,r,p);
	tr[k]=merge(tr[k<<1],tr[k<<1|1]);
}
inline LL ask_sum(int k,int l,int r,int L,int R) {
	if(L>R) return 0;
	if(L<=l && r<=R) return tr[k].s;
	int mid=(l+r)>>1;
	if(R<=mid) return ask_sum(k<<1,l,mid,L,R);
	else if(L>mid) return ask_sum(k<<1|1,mid+1,r,L,R);
	else return ask_sum(k<<1,l,mid,L,R)+ask_sum(k<<1|1,mid+1,r,L,R);
}
inline node ask(int k,int l,int r,int L,int R) {
	if(L<=l && r<=R) return tr[k];
	int mid=(l+r)>>1;
	if(R<=mid) return ask(k<<1,l,mid,L,R);
	else if(L>mid) return ask(k<<1|1,mid+1,r,L,R);
	else return merge(ask(k<<1,l,mid,L,R),ask(k<<1|1,mid+1,r,L,R));
}

int main() {
	n=rd(), q=rd();
	for(int i=1;i<=n;i++) a[i]=rd();
	for(int i=1;i<=n;i++) w[i]=rd();
	build(1,1,n);
	for(int i=1;i<=q;i++) {
		int x=rd(), y=rd();
		if(x<0) {
			w[-x]=y;
			inc(1,1,n,-x); 
		} else {
			int l=x, r=y, ans=l;
			while(l<=r) {
				int mid=(l+r)>>1;
				LL lc=ask_sum(1,1,n,x,mid);
				LL rc=ask_sum(1,1,n,mid+1,y);
				if(lc>=rc) ans=mid, r=mid-1;
				else l=mid+1;
			}
			ans=(ask(1,1,n,x,ans).sl+ask(1,1,n,ans,y).sr)%mod;
			W(ans), putchar('\n');
		}
	}
}

Linear Congruential Generator

最后每个函数图象呈ρ\rho型,且进入环之前的链长最多为11

答案为lcmc1,c2,...,cnlcm _{c_1,c_2,...,c_n}+最长链长,于是从大到小贪心即可。

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=2e6+50, mod=1e9+7;
int pr[N],pt,npr[N],mnpr[N];
int n,p[N],c[N],mx[N];

inline void sieve() {
	for(int i=2;i<N;i++) {
		if(!npr[i]) pr[++pt]=i, mnpr[i]=i;
		for(int j=1;j<=pt;j++) {
			long long k=i*pr[j];
			if(k>=N) break;
			mnpr[k]=pr[j];
			npr[k]=1;
			if(!(i%pr[j])) break;
		}
	}
}
int main() {
	sieve();
	n=rd();
	for(int i=1;i<=n;i++) p[i]=rd();
	sort(p+1,p+n+1);
	int bz=0, ans=1;
	for(int i=n;i>=1;i--) {
		if(!c[p[i]]) ++c[p[i]], ans=(long long)ans*p[i]%mod, mx[p[i]]=1;
		else {
			int v=--p[i]; 
			while(v!=1) {
				int u=mnpr[v], ci=0;
				while(!(v%u)) v/=u, ++ci;
				if(c[u]<ci) {
					for(int j=c[u]+1;j<=ci;j++) ans=(long long)ans*u%mod;
					c[u]=ci; mx[u]=1;
				} else mx[u]+=(c[u]==ci);
			}
		}
	}
	for(int i=1;i<=n;i++) {
		int v=p[i], tag=0; 
		while(v!=1) {
			int u=mnpr[v], ci=0;
			while(!(v%u)) v/=u, ++ci;
			if(c[u]==ci && mx[u]==1) tag=1;
		}
		if(!tag) {++ans; break;}
	}
	cout<<ans<<'\n';
}

Euler tour

如果区间包含,且一个数出现的奇偶位置不同,则一定不合法。

否则依次构造每个区间,不断舍弃形容y,x,yy,x,y的相邻三个数的后两个即可判断有无合法解,顺便构造出合法解。

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=1e6+50, L=21;
int n,a[N],c[N],li[N],ri[N],pre[N],lst[N],mn[N][21];
vector <int> unvis;
inline int ga(int *anc,int x) {return (anc[x]==x) ? x : (anc[x]=ga(anc,anc[x]));}
inline void solve(int l,int r) {
	vector <int> vec; int p=-1;
	for(int i=ga(ri,l);i<=r;i=ga(ri,i+1)) {
		vec.push_back(i); ++p;
		while(vec.size()>=3) {
			if(((!a[vec[p-2]] && a[i]) || (a[vec[p-2]] && !a[i]) || (a[vec[p-2]] && (a[vec[p-2]]==a[i]))) && a[vec[p-1]] ) {
				if(a[vec[p-2]]!=a[vec[p]])a[vec[p-2]]=a[i]=a[vec[p-2]]+a[i];
				vec.pop_back(); vec.pop_back();
				p-=2;
			} else break;
		}
	}	
	
	for(int j=1;j<vec.size();++j) if(a[vec[j]] && a[vec[j-1]]) {puts("no"); exit(0);}
	
	deque <int> q; int nowl=vec[0];
	for(int j=1;j<vec.size()-1;++j) q.push_back(vec[j]);
	while(!q.empty()) {
		int u=q.front(), v=q.back();
		if(q.size()==1) {
			if(!a[u]) {
				if(unvis.empty()) {puts("no"); exit(0);}
				a[u]=unvis.back(); unvis.pop_back();
			} break;
		} else {
			if(!a[u] && !a[v]) {
				if(unvis.empty()) {puts("no"); exit(0);}
				a[u]=a[v]=unvis.back(); unvis.pop_back();
				nowl=a[u]; q.pop_front(); q.pop_back();
			} else if(a[u]) {
				a[q[1]]=nowl; q.pop_front(); q.pop_front();
			} else {
				a[q[q.size()-2]]=nowl; q.pop_back(); q.pop_back();
			}
		}
	}
	for(int i=ga(ri,l);i<=r;i=ga(ri,i+1)) if(i!=l) ri[i]=r+1;
	li[r]=l;
}

inline void solve2() {
	if(unvis.size()) {
		a[1]=a[2*n-1]=unvis.back(); unvis.pop_back();
		solve(1,2*n-1); return;
	}
	vector <int> vec; int p=-1;
	for(int i=1;i<2*n;i=ga(ri,i+1)) {vec.push_back(i); ++p;}	
	int c0=0, c1=0;
	for(int j=0;j<vec.size();++j) if(a[vec[j]]) ++c1;
	for(int j=1;j<p;j++) {
		if(!a[vec[j]]) continue;
		--c1;
		if(vec[j]&1) {
			if(j>=2*c0 && p-j>=2*c1) {
				a[1]=a[2*n-1]=a[vec[j]]; solve(1,2*n-1);
				return;
			}
		}
		++c0;
	}
	puts("no"); exit(0);
}
int main() {
	n=rd();
	for(int i=1;i<2*n;i++) {
		a[i]=rd(); ++c[a[i]];
	}
	for(int i=1;i<=n;i++) if(!c[i]) unvis.push_back(i);
	
	if(a[1] && a[2*n-1] && a[1]!=a[2*n-1]) {puts("no"); return 0;}
	else if((a[1] || a[2*n-1]) && (a[1]!=a[2*n-1])) {a[1]=a[2*n-1]=a[1]+a[2*n-1];}
	
	for(int i=1;i<2*n;i++) {
		if(!a[i]) continue;
		pre[i]=(lst[a[i]] ? lst[a[i]] : i);
		lst[a[i]]=i;
	}
	
	for(int i=1;i<2*n;i++) {
		mn[i][0]=(pre[i] ? pre[i] : i);
		if(a[i] && ((i-pre[i])%2)) {puts("no"); return 0;}
		for(int j=1;j<L && (i>=(1<<j));j++) mn[i][j]=min(mn[i][j-1],mn[i-(1<<(j-1))][j-1]);
		if(a[i] && pre[i]<i) {
			int mx=i, pos=i-1;
			for(int j=L-1;~j;j--) if(pos-(1<<j)+1>pre[i]) mx=min(mx,mn[pos][j]), pos-=(1<<j);
			if(mx<=pre[i]) {puts("no"); return 0;}
		}
	}
	
	for(int i=1;i<=2*n;i++) ri[i]=i, li[i]=i;
	for(int i=2;i<2*n;i++) if(a[i] &&  ga(li,pre[i])<i) 
		solve(ga(li,pre[i]),i);
	
	if(!a[1] && !a[2*n-1]) solve2();
	puts("yes");
	for(int i=1;i<2*n;i++) printf("%d ",a[i]);
}