Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)
Posted wawawa8
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)相关的知识,希望对你有一定的参考价值。
考场上只做出了ABDE
C都挂了。。。
题解:
A
题解:
模拟
判断前面一段是否相同,后面一段是否相同,长度是否够(不能有重叠)
Code:
1 #include<stdio.h> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<vector> 6 #include<map> 7 #include<set> 8 #include<cmath> 9 #include<iostream> 10 #include<queue> 11 #include<string> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,int> pii; 15 typedef long double ld; 16 typedef unsigned long long ull; 17 typedef pair<long long,long long> pll; 18 #define fi first 19 #define se second 20 #define pb push_back 21 #define mp make_pair 22 #define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++) 23 #define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) 24 25 ll read(){ 26 ll x=0,f=1;char c=getchar(); 27 while(c<‘0‘ || c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 28 while(c>=‘0‘ && c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} 29 return x*f; 30 } 31 32 int n,m; 33 string a,b; 34 35 int main(){ 36 n=read(),m=read(); 37 cin>>a>>b; 38 int pos=-1; 39 for(int i=0;i<n;i++){ 40 if(a[i]==‘*‘){ 41 pos=i; 42 break; 43 } 44 } 45 if(pos==-1){ 46 if(a==b) puts("YES"); 47 else puts("NO"); 48 return 0; 49 } 50 51 if(n>m+1){ 52 puts("NO"); 53 return 0; 54 } 55 56 for(int i=0;i<pos;i++){ 57 if(a[i]!=b[i]){ 58 puts("NO"); 59 return 0; 60 } 61 } 62 for(int i=n-1;i>pos;i--){ 63 if(a[i]!=b[i-n+m]){ 64 puts("NO"); 65 return 0; 66 } 67 } 68 puts("YES"); 69 return 0; 70 }
B
题解:
简单计算
考虑几种情况:
1. k<=n+1 那么任意一种构造都可行 答案为(k-1)/2
2. k>n+n-1 没有可行解 答案为零
3. 从(k-n)+n到(k/2+k/2) 分k的奇偶性讨论一下
Code:
1 #include<stdio.h> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<vector> 6 #include<map> 7 #include<set> 8 #include<cmath> 9 #include<iostream> 10 #include<queue> 11 #include<string> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,int> pii; 15 typedef long double ld; 16 typedef unsigned long long ull; 17 typedef pair<long long,long long> pll; 18 #define fi first 19 #define se second 20 #define pb push_back 21 #define mp make_pair 22 #define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++) 23 #define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) 24 25 ll read(){ 26 ll x=0,f=1;char c=getchar(); 27 while(c<‘0‘ || c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 28 while(c>=‘0‘ && c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} 29 return x*f; 30 } 31 32 ll n,k; 33 34 int main(){ 35 n=read();k=read(); 36 ll ans=0; 37 if(k<=n+1) ans=(k-1)/2; 38 else if(k>n+n-1) ans=0; 39 else{ 40 ll nw=k/2; 41 ll l=k-n; 42 if(k%2==0) nw--; 43 ans=nw-l+1; 44 } 45 cout<<ans<<endl; 46 return 0; 47 }
C
题解:
模拟
看到(就加进去 直到够了为止
但是如果用string s; s+=‘(‘;
由于string特别慢 于是会超时。。。
所以我们改用数组存储每一位是(还是)
Code:
1 #include<stdio.h> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<vector> 6 #include<map> 7 #include<set> 8 #include<cmath> 9 #include<iostream> 10 #include<queue> 11 #include<string> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,int> pii; 15 typedef long double ld; 16 typedef unsigned long long ull; 17 typedef pair<long long,long long> pll; 18 #define fi first 19 #define se second 20 #define pb push_back 21 #define mp make_pair 22 #define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++) 23 #define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) 24 25 ll read(){ 26 ll x=0,f=1;char c=getchar(); 27 while(c<‘0‘ || c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 28 while(c>=‘0‘ && c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} 29 return x*f; 30 } 31 32 int n,m; 33 string s; 34 string ans; 35 int res[200200],sz; 36 37 int main(){ 38 n=read(),m=read(); 39 cin>>s; 40 int num=m/2; 41 int nw=0,dif=0; 42 for(int i=0;i<s.size();i++){ 43 if(s[i]==‘(‘){ 44 nw++;dif++; 45 res[++sz]=1; 46 if(nw==num) break; 47 } 48 else{ 49 if(dif){ 50 res[++sz]=2; 51 dif--; 52 } 53 } 54 } 55 while(dif--) res[++sz]=2; 56 for(int i=1;i<=sz;i++) 57 if(res[i]==1) putchar(‘(‘); else putchar(‘)‘); 58 puts(""); 59 return 0; 60 }
D
题解:
首先我们把整个刷上1
然后0的情况就没有了
剩下我们按照题意模拟
每个数我们找到最左的位置和最右的位置
在线段树上更新 把这段区间刷成这个数
注意如果最大的数没有出现 那么我们得加上这个数 因为他是最后刷的 所以可以放在任何为0的位置上
然后如果现在的这个序列和原来的有矛盾(原来某一位和现在不同) 那么就是-1
否则输出这个序列
Code:
1 #include<stdio.h> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<vector> 6 #include<map> 7 #include<set> 8 #include<cmath> 9 #include<iostream> 10 #include<queue> 11 #include<string> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,int> pii; 15 typedef long double ld; 16 typedef unsigned long long ull; 17 typedef pair<long long,long long> pll; 18 #define fi first 19 #define se second 20 #define pb push_back 21 #define mp make_pair 22 #define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++) 23 #define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) 24 25 ll read(){ 26 ll x=0,f=1;char c=getchar(); 27 while(c<‘0‘ || c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 28 while(c>=‘0‘ && c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} 29 return x*f; 30 } 31 32 const int maxn=200200; 33 int n,q; 34 int a[maxn]; 35 int l[maxn],r[maxn]; 36 37 struct Node{ 38 int l,r,val; 39 int tag; 40 } tr[maxn*4]; 41 42 #define lc (i<<1) 43 #define rc (i<<1|1) 44 45 void build(int i,int l,int r){ 46 tr[i].l=l,tr[i].r=r; 47 if(l==r) 48 return; 49 int md=(l+r)>>1; 50 build(lc,l,md); 51 build(rc,md+1,r); 52 } 53 54 void pushdown(int i){ 55 if(!tr[i].tag) return; 56 tr[lc].tag=tr[rc].tag=tr[lc].val=tr[rc].val=tr[i].tag; 57 tr[i].tag=0; 58 return; 59 } 60 61 void upd(int i,int l,int r,int v){ 62 if(tr[i].l>=l && tr[i].r<=r){ 63 tr[i].val=v; 64 tr[i].tag=v; 65 return; 66 } 67 if(tr[i].l>r || tr[i].r<l) return; 68 pushdown(i); 69 upd(lc,l,r,v);upd(rc,l,r,v); 70 } 71 72 int ask(int i,int pos){ 73 if(tr[i].l>pos || tr[i].r<pos) return 0; 74 if(tr[i].l==tr[i].r) return tr[i].val; 75 pushdown(i); 76 return max(ask(lc,pos),ask(rc,pos)); 77 } 78 79 int main(){ 80 n=read(),q=read(); 81 bool ok=0; 82 int mx=0; 83 rep(i,1,n){ 84 a[i]=read(); 85 if(a[i]==0) ok=1; 86 mx=max(mx,a[i]); 87 } 88 if(!ok){ 89 if(mx!=q){ 90 puts("NO"); 91 return 0; 92 } 93 } 94 95 if(mx!=q){ 96 rep(i,1,n){ 97 if(a[i]==0){ 98 a[i]=q; 99 break; 100 } 101 } 102 } 103 104 rep(i,1,n){ 105 int nw=a[i]; 106 if(l[nw]==0) l[nw]=i; 107 r[nw]=max(r[nw],i); 108 } 109 110 build(1,1,n); 111 l[1]=1,r[1]=n; 112 rep(i,1,q) 113 if(l[i]) upd(1,l[i],r[i],i); 114 115 rep(i,1,n){ 116 int nw=ask(1,i); 117 if(a[i] && a[i]!=nw){ 118 puts("NO"); 119 return 0; 120 } 121 a[i]=nw; 122 } 123 124 puts("YES"); 125 rep(i,1,n) 126 printf("%d ",a[i]); 127 puts(""); 128 129 return 0; 130 }
E
题解:
交互题
很有趣
首先我们可以方便的得出前n-1步
就是每次询问当前格子向右的一个格子能不能到(n,n)
如果能 那么向右走 否则向下走
这样我们可以走到对角线上
然后不能这么询问了
所以我们反过来做
但是因为路径不止一条 我们有可能不能走到同一个对角线上的格子
怎么办呢
我们换一种询问方式
从(n,n)开始
然后每次询问当前格子的上方一个格子能否到达之前哪条路径上与之距离为n-1的那个格子
具体见代码
如果能走 就往上走 否则往左走
为什么是对的呢
因为我们一定会得到所有路径里最靠右的那一条路径
Code:
1 #include<stdio.h> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<vector> 6 #include<map> 7 #include<set> 8 #include<cmath> 9 #include<iostream> 10 #include<queue> 11 #include<string> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,int> pii; 15 typedef long double ld; 16 typedef unsigned long long ull; 17 typedef pair<long long,long long> pll; 18 #define fi first 19 #define se second 20 #define pb push_back 21 #define mp make_pair 22 #define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++) 23 #define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) 24 25 ll read(){ 26 ll x=0,f=1;char c=getchar(); 27 while(c<‘0‘ || c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 28 while(c>=‘0‘ && c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} 29 return x*f; 30 } 31 32 int n; 33 string ans1,ans2; 34 35 bool ask(int a,int b,int c,int d){ 36 printf("? %d %d %d %d ",a,b,c,d); 37 fflush(stdout); 38 string ret; 39 cin>>ret; 40 if(ret=="YES") return 1; 41 else return 0; 42 } 43 44 int main(){ 45 n=read(); 46 int nwx=1,nwy=1; 47 for(int i=1;i<n;i++){ 48 bool nw=ask(nwx,nwy+1,n,n); 49 if(nw) ans1=ans1+‘R‘,nwy++; 50 else ans1=ans1+‘D‘,nwx++; 51 } 52 int xx=n,yy=n; 53 for(int i=n-2;i>=0;i--){ 54 if(ans1[i]==‘R‘) nwy--; 55 else nwx--; 56 bool nw=ask(nwx,nwy,xx-1,yy); 57 if(nw) ans2=‘D‘+ans2,xx--; 58 else ans2=‘R‘+ans2,yy--; 59 } 60 cout<<"! "<<ans1<<ans2<<endl; 61 fflush(stdout); 62 return 0; 63 }
F
题解:
好题
首先我们先把那些“我的路径”加进图中
用并查集维护连通性
然后对于每一条新的路径:
如果两端在一个联通块内 那么记录下来
否则加进图中 并且更新并查集
这样我们得到一棵树和一些边
然后dfs一遍整理树的结构 求出每个点的father和depth
下面是精华部分
我们还是用一个并查集维护这棵树
现在我们要做的操作是:对于之前每条未加进图中的边,我们把两端点之间的路径更新成这条边的边权,不能重复更新
因为输入的时候就是排好序的所以不需要重复更新
问题在于每条边如何正好被更新一次
就是说我们在更新后边的时候要跳过一些前边被更新过的边
我们用fa[x]表示这个点在往上跳的时候跳到的点 也就是说从x到fa[x]的路径都被更新过 并且fa[x]到f[fa[x]]这条边没有被更新
那么直接这样跳一跳直到两个端点跳到同一个点就结束了
怎么维护fa呢
我们只需要在往上跳的时候令fa[x]=fp(f[x])就可以了 fp在这里表示的就是找到上一个没有更新的点
Code:
1 #include<stdio.h> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<vector> 6 #include<map> 7 #include<set> 8 #include<cmath> 9 #include<iostream> 10 #include<queue> 11 #include<string> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,int> pii; 15 typedef long double ld; 16 typedef unsigned long long ull; 17 typedef pair<long long,long long> pll; 18 #define fi first 19 #define se second 20 #define pb push_back 21 #define mp make_pair 22 #define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++) 23 #define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) 24 25 ll read(){ 26 ll x=0,f=1;char c=getchar(); 27 while(c<‘0‘ || c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 28 while(c>=‘0‘ && c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} 29 return x*f; 30 } 31 32 const int maxn=500500; 33 34 int n,m,k,num; 35 int fa[maxn]; 36 37 struct Edge{ 38 int fr,to,len,tp; 39 }; 40 vector<Edge> edges; 41 vector<int> gr[maxn]; 42 43 inline int fp(int x){if(fa[x]==x) return x;return fa[x]=fp(fa[x]);} 44 inline void uni(int a,int b){a=fp(a),b=fp(b);if(a!=b) fa[a]=b;} 45 46 void add_edge(int a,int b,int l,int t){ 47 edges.pb((Edge){a,b,l,t}); 48 edges.pb((Edge){b,a,l,t}); 49 num=edges.size(); 50 gr[a].pb(num-2); 51 gr[b].pb(num-1); 52 } 53 54 int A[maxn],B[maxn],L[maxn],cnt; 55 int f[maxn],d[maxn],res[maxn]; 56 57 void dfs(int x,int pa=1){ 58 f[x]=pa; 59 for(int i=0;i<gr[x].size();i++){ 60 int ind=gr[x][i]; 61 Edge nw=edges[ind]; 62 if(nw.to==f[x]) continue; 63 d[nw.to]=d[x]+1; 64 dfs(nw.to,x); 65 } 66 } 67 68 int ans[maxn]; 69 70 int main(){ 71 // freopen("in","r",stdin); 72 n=read(),k=read(),m=read(); 73 rep(i,1,n) fa[i]=i; 74 for(int i=1;i<=k;i++){ 75 int a=read(),b=read(); 76 add_edge(a,b,0,0); 77 uni(a,b); 78 } 79 for(int i=1;i<=m;i++){ 80 int x=read(),y=read(),l=read(); 81 int fx=fp(x),fy=fp(y); 82 if(fx!=fy){fa[fx]=fy;add_edge(x,y,l,1);} 83 else{A[++cnt]=x,B[cnt]=y,L[cnt]=l;} 84 } 85 86 d[1]=1; 87 dfs(1); 88 89 for(int i=1;i<=n;i++) 90 fa[i]=i; 91 92 for(int i=1;i<=cnt;i++){ 93 int nwx=A[i],nwy=B[i],nwl=L[i]; 94 nwx=fp(nwx),nwy=fp(nwy); 95 while(nwx!=nwy){ 96 if(d[nwx]>=d[nwy]){ 97 res[nwx]=nwl; 98 fa[nwx]=fp(f[nwx]); 99 nwx=fa[nwx]; 100 } 101 else{ 102 res[nwy]=nwl; 103 fa[nwy]=fp(f[nwy]); 104 nwy=fa[nwy]; 105 } 106 } 107 } 108 109 //for(int i=1;i<=n;i++) cout<<res[i]<<endl; 110 111 ll ans=0; 112 for(int i=1;i<=n;i++){ 113 for(int j=0;j<gr[i].size();j++){ 114 int ind=gr[i][j]; 115 Edge nw=edges[ind]; 116 if(nw.to==f[i] && nw.tp==0){ 117 if(fa[i]==i){ 118 puts("-1"); 119 return 0; 120 } 121 ans+=res[i]; 122 } 123 } 124 } 125 cout<<ans<<endl; 126 return 0; 127 } 128
总结
1. 字符串string类很慢 尽量不要用string加string的操作
2. 想好了再写 不要出现细节错误
以上是关于Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #504 E - Down or Right 交互题
Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)
Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)
Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) A. Single Wildcard Patter
Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) D. Array Restoration(示例代码
E - Down or Right Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)