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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

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\n",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 }
View Code

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     
View Code

总结

1. 字符串string类很慢 尽量不要用string加string的操作

2. 想好了再写 不要出现细节错误

猜你喜欢

转载自www.cnblogs.com/wawawa8/p/9496391.html