Codeforces Round #512 (Div. 1) 简要题解
程序员文章站
2022-05-09 22:07:50
...
Vasya and Triangle
用叉积来计算面积就可以知道最后面积一定是 0.5 的倍数,也就是把与约分后最后为或者。 然后分两种情况讨论即可。
#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
一段区间合法那么是偶数且。 注意到区间长度大于就只与前缀奇偶有关了,可以记两个前缀和。小于暴力枚举。
#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
最后每个函数图象呈型,且进入环之前的链长最多为。
答案为+最长链长,于是从大到小贪心即可。
#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
如果区间包含,且一个数出现的奇偶位置不同,则一定不合法。
否则依次构造每个区间,不断舍弃形容的相邻三个数的后两个即可判断有无合法解,顺便构造出合法解。
#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]);
}
上一篇: 老师,见识一下*学渣的厉害吧!
下一篇: 爆笑之逗B剧场第95季
推荐阅读
-
Codeforces Round #595 (Div. 3)D1D2 贪心 STL
-
Codeforces Round #443 (Div. 1) CodeForces - 878 A
-
Codeforces Round #621 (Div. 1 + Div. 2)
-
Codeforces Round #658 (Div. 2)C1. Prefix Flip (Easy Version)(贪心)
-
Codeforces Round #658 (Div. 2) (C1、C2)
-
Codeforces Round #659 (Div. 2) 题解
-
Codeforces Round #583 (Div. 1 + Div. 2,) D. Treasure Island(dfs+思维)
-
Codeforces Round #654 (Div. 2) - 题解
-
Codeforces Round #659 (Div. 2) C、String Transformation 1(思维+set)
-
Educational Codeforces Round 98 (Rated for Div. 2) A-E 题解