Educational Codeforces Round 22
Problems
# | Name | ||
---|---|---|---|
A |
standard input/output
2 s, 256 MB |
x1629 | |
B |
standard input/output
1 s, 256 MB |
x506 | |
C |
standard input/output
1 s, 256 MB |
x656 | |
D |
standard input/output
2 s, 256 MB |
x21 | |
E |
standard input/output
2 s, 256 MB |
x92 | |
F |
standard input/output
6 s, 256 MB |
x25 |
A
水题 不解释
#include <bits/stdc++.h> using namespace std; int n,m,xx,yy,sum; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&xx),sum+=xx; scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d",&xx,&yy); if(xx<=sum&&yy>=sum){printf("%d\n",sum);return 0;} else if(sum<xx){printf("%d\n",xx);return 0;} }puts("-1"); }
B
这题全是细节
要判有没有爆long long还有边界情况
#include <bits/stdc++.h> using namespace std; #define int long long int x,y,l,r,ans; set<int>s; bool check(int x,int y){return log10(x)+log10(y)>18;} signed main(){ scanf("%I64d%I64d%I64d%I64d",&x,&y,&l,&r); for(int i=0,t=1;;i++,t=t*x){ if(t>r)break; for(int j=0,w=1;;j++,w=w*y){ if(t+w>r)break; if(t+w>=l)s.insert(t+w); if(check(w,y))break; } if(check(t,x))break; } if(s.empty()){printf("%I64d\n",r-l+1);return 0;} ans=max(*s.begin()-l,0ll); for(set<int>::iterator it=s.begin(),it2;it!=s.end();it++){ it2=it; if(it!=s.begin())it2--; ans=max(ans,*it-*it2-1); it2=it,it2++; if(it2==s.end())ans=max(ans,r-*it); }printf("%I64d\n",ans); }
C
贪心
在不被追到的情况下走的最远
一遍DFS即可 (为什么题解全是2遍dfs的 难以理解)
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=400050; int n,x,first[N],nxt[N],v[N],tot,deep[N],xx,yy,rec[N],fa[N],ans; void add(int x,int y){v[tot]=y,nxt[tot]=first[x],first[x]=tot++;} void dfs(int x){ for(int i=first[x];~i;i=nxt[i])if(v[i]!=fa[x]) fa[v[i]]=x,deep[v[i]]=deep[x]+1,dfs(v[i]),rec[x]=max(rec[x],rec[v[i]]+1); } int main(){ memset(first,-1,sizeof(first)); scanf("%d%d",&n,&x); for(int i=1;i<n;i++)scanf("%d%d",&xx,&yy),add(xx,yy),add(yy,xx); deep[1]=1,dfs(1); ans=max(ans,(deep[x]-1+rec[x])*2); for(int i=x,t=0;;i=fa[i],t++){ if(deep[x]-t*2<2)break; ans=max(ans,(deep[i]-1)*2+rec[i]*2); }printf("%d\n",ans); }
D
DP
f[i][j] A选a[i] B选[j]的最长长度
维护两个数组 X[i]表示mod 7 为i的最长长度
Y[i]表示数字是i的最长长度
为了去重
只从i<j转移 更新i>j的情况
if(i<j)ans=max(ans,f[j][i]=f[i][j]=max(max(Y[a[j]+1],max(Y[a[j]-1],X[a[j]%7])),f[i][0])+1);
X[a[j]%7]=max(X[a[j]%7],f[i][j]),Y[a[j]]=max(Y[a[j]],f[i][j]);
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=5050; int f[N][N],a[N],n,X[7],Y[100500],ans; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=0;i<=n;i++){ memset(X,0,sizeof(X)),memset(Y,0,sizeof(Y)); for(int j=1;j<=n;j++){ if(i==j)continue; if(i<j)ans=max(ans,f[j][i]=f[i][j]=max(max(Y[a[j]+1],max(Y[a[j]-1],X[a[j]%7])),f[i][0])+1); X[a[j]%7]=max(X[a[j]%7],f[i][j]),Y[a[j]]=max(Y[a[j]],f[i][j]); } } printf("%d\n",ans); }
E
一个点有没有被算到答案里
只跟它k次之前出现的地方有没有小于l有关
那 主席树直接上
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=100050; vector<int>vec[N]; int n,k,q,xx,yy,a[N],jy,s[N],lson[N*66],rson[N*66],tree[N*66],cnt,root[N],lst; void insert(int l,int r,int &pos,int last,int wei){ pos=++cnt;tree[pos]=tree[last]+1; if(l==r)return; int mid=(l+r)>>1; if(mid<wei)lson[pos]=lson[last],insert(mid+1,r,rson[pos],rson[last],wei); else rson[pos]=rson[last],insert(l,mid,lson[pos],lson[last],wei); } int query(int l,int r,int pos,int last,int L,int R){ if(l>=L&&r<=R)return tree[pos]-tree[last]; int mid=(l+r)>>1; if(mid<L)return query(mid+1,r,rson[pos],rson[last],L,R); else if(mid>=R)return query(l,mid,lson[pos],lson[last],L,R); else return query(l,mid,lson[pos],lson[last],L,R)+query(mid+1,r,rson[pos],rson[last],L,R); } int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); vec[a[i]].push_back(i),jy=vec[a[i]].size()-1; s[i]=jy>=k?vec[a[i]][jy-k]:0,insert(0,N,root[i],root[i-1],s[i]); } scanf("%d",&q); while(q--){ scanf("%d%d",&xx,&yy),xx=(xx+lst)%n+1,yy=(yy+lst)%n+1; if(xx>yy)swap(xx,yy); printf("%d\n",lst=query(0,N,root[yy],root[xx-1],0,xx-1)); } }
F
BZOJ 4025
并查集+cdq分治
我打的是线段树+vector
最后DFS一遍
效果一样
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=100050; int n,q,f[N],top,size[N],dis[N]; struct Edge{int from,to,tim;Edge(){}Edge(int x,int y){from=x,to=y;}}edge[N]; struct Update{int fx,fy,disx;Update(){}Update(int x,int y,int z){fx=x,fy=y,disx=z;}}upd[N]; bool operator<(Edge a,Edge b){if(a.from!=b.from)return a.from<b.from;return a.to<b.to;} set<Edge>st;set<Edge>::iterator it;vector<Edge>vec[N*8]; void insert(int l,int r,int pos,int L,int R,Edge t){ if(l>=L&&r<=R){vec[pos].push_back(t);return;} int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1; if(mid<L)insert(mid+1,r,rson,L,R,t); else if(mid>=R)insert(l,mid,lson,L,R,t); else insert(l,mid,lson,L,R,t),insert(mid+1,r,rson,L,R,t); } int find(int x){return x==f[x]?x:find(f[x]);} void merge(int x,int y,int z){ if(size[x]>size[y])swap(x,y); upd[++top]=Update(x,y,dis[x]); f[x]=y,dis[x]=z,size[y]+=size[x]; } bool get_dis(int x){ int r=0; while(f[x]!=x)r^=dis[x],x=f[x]; return r; } void query(int l,int r,int pos){ int rec=top; for(int i=0;i<vec[pos].size();i++){ int x=find(vec[pos][i].from),y=find(vec[pos][i].to),z=get_dis(vec[pos][i].from)^get_dis(vec[pos][i].to)^1; if(x!=y)merge(x,y,z); else if(z&1){for(int j=l;j<=r;j++)puts("NO");goto ed;} } if(l==r)puts("YES"); else query(l,(l+r)>>1,pos<<1),query((l+r)/2+1,r,pos<<1|1); ed:for(int i=top;i>rec;i--){ int fx=upd[i].fx,fy=upd[i].fy; dis[fx]=0,f[fx]=fx,size[fy]-=size[fx]; }top=rec; } int main(){ scanf("%d%d",&n,&q); for(int i=1;i<=n;i++)f[i]=i; for(int i=1;i<=q;i++){ scanf("%d%d",&edge[i].from,&edge[i].to);edge[i].tim=i; if((it=st.find(edge[i]))==st.end())st.insert(edge[i]); else insert(1,q,1,it->tim,i-1,edge[i]),st.erase(it); } for(it=st.begin();it!=st.end();it++)insert(1,q,1,it->tim,q,*it); query(1,q,1); }