Codeforces Round #416 (Div. 2)

A.Vladik and Courtesy

题目链接:http://codeforces.com/contest/811/problem/A

暴力

代码如下:

 1 #include <iostream>
 2 using namespace std;
 3 typedef long long ll;
 4 ll a,b;
 5 int main(void){
 6     cin>>a>>b;
 7     ll t=1;
 8     while(1){
 9         if(t&1)a-=t;
10         else b-=t;
11         t++;
12         if(a<0||b<0)break;
13     }
14     if(a<0)cout<<"Vladik";
15     else cout<<"Valera";
16 }
View Code

B.Vladik and Complicated Book

题目链接:http://codeforces.com/contest/811/problem/B

题目大意:判断区间内第$k$大元素是否为$x$.

离线+树状数组/主席树模板/暴力

看到数据范围$10^4$,想成学校的老年机,想半天想出个$O(mlgm+mlgn)$的,结果被告知$O(nm)$暴力可过= =

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long ll;
 6 int n,m,a[10005],c[10005],f[10005];
 7 bool ans[10005];
 8 struct node{
 9     int l,r,x,id;
10     friend bool operator<(node qq,node pp){
11         return a[qq.x]<a[pp.x];
12     }
13 }q[10005];
14 int lowbit(int x){
15     return x&-x;
16 }
17 void add(int x){
18     for(int i=x;i<=n;i+=lowbit(i))
19         c[i]++;
20 }
21 int sum(int x){
22     int ans=0;
23     for(int i=x;i>0;i-=lowbit(i))
24         ans+=c[i];
25     return ans;
26 }
27 int main(void){
28     scanf("%d%d",&n,&m);
29     for(int i=1;i<=n;++i){
30         scanf("%d",&a[i]);
31         f[a[i]]=i;
32     }
33     for(int i=0;i<m;++i){
34         scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].x);
35         q[i].id=i;
36     }
37     sort(q,q+m);
38     int l=1;
39     for(int i=0;i<m;++i){
40         int id=q[i].id;
41         while(l<a[q[i].x]){
42             add(f[l]);
43             l++;
44         }
45         int t=sum(q[i].r)-sum(q[i].l-1);
46         if(q[i].l+t==q[i].x)ans[id]=1;
47         else ans[id]=0;
48     }
49     for(int i=0;i<m;++i){
50         if(ans[i])printf("Yes
");
51         else printf("No
");
52     }
53 }
View Code

C.Vladik and Memorable Trip

题目链接:http://codeforces.com/contest/811/problem/C

题目大意:将一个数组划分成若干个不交叉的块,要求块外不含块内元素,每个块的价值为块内不同元素的异或值,总价值为所有块的价值和,问最大价值。

DP

想着先区间合并再dp,然后算法错误...

看到数据范围其实$O(n^2)$可过,直接dp就好了...

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 typedef long long ll;
 7 int n,a[5005],dp[5005],r[5005];
 8 bool vis[5005],f[5005];
 9 int main(void){
10     scanf("%d",&n);
11     for(int i=0;i<n;++i){
12         scanf("%d",&a[i]);
13         r[a[i]]=i;
14     }
15     int ans=0;
16     for(int i=0;i<n;++i){
17         int t=a[i];
18         if(!vis[t]){
19             vis[t]=1;
20             memset(f,0,sizeof(f));
21             f[t]=1;
22             bool flag=1;
23             int temp=t;
24             int R=r[t];
25             for(int j=i+1;j<R;++j){
26                 if(vis[a[j]]&&a[j]!=t){
27                     flag=0;break;
28                 }
29                 if(!f[a[j]]){
30                     temp^=a[j];
31                     R=max(R,r[a[j]]);
32                     f[a[j]]=1;
33                 }
34             }
35             if(flag)dp[R]=max(dp[R],temp+ans);
36         }
37         ans=max(ans,dp[i]);
38     }
39     printf("%d
",ans);
40 }
View Code

D.Vladik and Favorite Game

题目链接:http://codeforces.com/contest/811/problem/D

题目大意:交互题,要求输出从起点到终点的行动方向,其中左右和上下的方向可能会被改变一次。

XJB模拟

先dfs出不改变方向的情况下的原行动方向,然后一步一步模拟即可。

代码如下:

  1 #include <cstdio>
  2 using namespace std;
  3 int n,m,d=-1,x,y,px,py,nx,ny;
  4 char mp[105][105];
  5 char ans[10005];
  6 bool vis[105][105];
  7 void dfs(int px,int py,int k){
  8     if(mp[px][py]=='F'){
  9         d=k;
 10         return;
 11     }
 12     int heng=0,shu=0;
 13     if(px-1>=0&&mp[px-1][py]!='*')shu++;
 14     if(px+1<n&&mp[px+1][py]!='*')shu++;
 15     if(py-1>=0&&mp[px][py-1]!='*')heng++;
 16     if(py+1<m&&mp[px][py+1]!='*')heng++;
 17     if(shu>heng){
 18         if(px-1>=0&&!vis[px-1][py]&&mp[px-1][py]!='*'){
 19             vis[px-1][py]=1;
 20             ans[k]='U';
 21             dfs(px-1,py,k+1);
 22             if(d!=-1)return;
 23         }
 24         if(px+1<n&&!vis[px+1][py]&&mp[px+1][py]!='*'){
 25             vis[px+1][py]=1;
 26             ans[k]='D';
 27             dfs(px+1,py,k+1);
 28             if(d!=-1)return;
 29         }
 30         if(py-1>=0&&!vis[px][py-1]&&mp[px][py-1]!='*'){
 31             vis[px][py-1]=1;
 32             ans[k]='L';
 33             dfs(px,py-1,k+1);
 34             if(d!=-1)return;
 35         }
 36         if(py+1<m&&!vis[px][py+1]&&mp[px][py+1]!='*'){
 37             vis[px][py+1]=1;
 38             ans[k]='R';
 39             dfs(px,py+1,k+1);
 40             if(d!=-1)return;
 41         }
 42     }else{
 43         if(py-1>=0&&!vis[px][py-1]&&mp[px][py-1]!='*'){
 44             vis[px][py-1]=1;
 45             ans[k]='L';
 46             dfs(px,py-1,k+1);
 47             if(d!=-1)return;
 48         }
 49         if(py+1<m&&!vis[px][py+1]&&mp[px][py+1]!='*'){
 50             vis[px][py+1]=1;
 51             ans[k]='R';
 52             dfs(px,py+1,k+1);
 53             if(d!=-1)return;
 54         }
 55         if(px-1>=0&&!vis[px-1][py]&&mp[px-1][py]!='*'){
 56             vis[px-1][py]=1;
 57             ans[k]='U';
 58             dfs(px-1,py,k+1);
 59             if(d!=-1)return;
 60         }
 61         if(px+1<n&&!vis[px+1][py]&&mp[px+1][py]!='*'){
 62             vis[px+1][py]=1;
 63             ans[k]='D';
 64             dfs(px+1,py,k+1);
 65             if(d!=-1)return;
 66         }
 67     }
 68 }
 69 char another(char c){
 70     if(c=='R')return 'L';
 71     if(c=='L')return 'R';
 72     if(c=='U')return 'D';
 73     if(c=='D')return 'U';
 74 }
 75 int main(void){
 76     scanf("%d%d",&n,&m);
 77     for(int i=0;i<n;++i)scanf("%s",mp[i]);
 78     dfs(0,0,0);
 79     px=nx=0,py=ny=0;
 80     bool heng=1,shu=1;
 81     for(int i=0;i<d;){
 82         bool LR=ans[i]=='L'||ans[i]=='R';
 83         bool UD=ans[i]=='U'||ans[i]=='D';
 84         if(LR){
 85             if(heng)printf("%c
",ans[i]);
 86             else printf("%c
",another(ans[i]));
 87             if(ans[i]=='R')ny=py+1;
 88             else ny=py-1;
 89         }else{
 90             if(shu)printf("%c
",ans[i]);
 91             else printf("%c
",another(ans[i]));
 92             if(ans[i]=='D')nx=px+1;
 93             else nx=px-1;
 94         }
 95         fflush(stdout);
 96         scanf("%d%d",&x,&y);x--,y--;
 97         if((x==-2&&y==-2)||mp[x][y]=='F')return 0;
 98         if(x==px&&y==py){
 99             if(ans[i]=='L'&&y+1>=m)heng=0;
100             if(ans[i]=='R'&&y-1<0)heng=0;
101             if(ans[i]=='D'&&x-1<0)shu=0;
102             if(ans[i]=='U'&&x+1>=n)shu=0;
103         }else if(x!=nx||y!=ny){
104             if(ans[i]=='R'&&y!=ny){
105                 heng=0;
106                 printf("L
");
107                 fflush(stdout);
108                 scanf("%d%d",&x,&y);x--,y--;
109             }
110             if(ans[i]=='L'&&y!=ny){
111                 heng=0;
112                 printf("R
");
113                 fflush(stdout);
114                 scanf("%d%d",&x,&y);x--,y--;
115             }
116             if(ans[i]=='U'&&y!=ny){
117                 shu=0;
118                 printf("D
");
119                 fflush(stdout);
120                 scanf("%d%d",&x,&y);x--,y--;
121             }
122             if(ans[i]=='D'&&y!=ny){
123                 shu=0;
124                 printf("U
");
125                 fflush(stdout);
126                 scanf("%d%d",&x,&y);x--,y--;
127             }
128         }else i++;
129         nx=px=x,ny=py=y;
130     }
131 }
View Code

E.Vladik and Entertaining Flags

题目链接:http://codeforces.com/contest/811/problem/E

题目大意:有一个$n imes m$的矩阵,$q$次询问,每次询问$l$列到$r$列围成的图中有多少连通块。

线段树+并查集

注意到$n leqslant 10$,故可以用线段树维护。

每段维护从$L$列到$R$列的图中有多少连通块,以及$L$列及$R$列的段内数字编号(保证段内的联通的数字编号是相同的)。

段与段合并时,只需判断相邻的数字是否相同,若相同且不为同一连通块,则合并。

查询前,需要将段两端的数字编号的$pre$指向自己(build操作中有可能将$pre$指向了其他段中的数字编号;同时因为段内联通的数字编号相同,故该操作不会改变段内数字的连通性),之后同合并操作。

复杂度$O(nmlgm+qnlgm)$.

代码如下:

  1 #include <cstdio>
  2 #define lson x<<1,l,mid
  3 #define rson x<<1|1,mid+1,r
  4 using namespace std;
  5 int n,m,q,mp[12][100005],pre[1000005],tot;
  6 bool flag;
  7 struct node{
  8     int num;
  9     int L[12],R[12];
 10 }a[100005<<2],ans;
 11 void init(int x){
 12     for(int i=0;i<=x;++i)pre[i]=i;
 13 }
 14 int Find(int x){
 15     return pre[x]==x?x:pre[x]=Find(pre[x]);
 16 }
 17 void Union(int a,int b){
 18     int x=Find(a),y=Find(b);
 19     if(x!=y)pre[x]=y;
 20 }
 21 void push_up(int x,int mid){
 22     int l=x<<1,r=x<<1|1;
 23     a[x].num=a[l].num+a[r].num;
 24     for(int i=0;i<n;++i){
 25         if(mp[i][mid]==mp[i][mid+1]){
 26             if(Find(a[l].R[i])!=Find(a[r].L[i])){
 27                 a[x].num--;
 28                 Union(a[l].R[i],a[r].L[i]);
 29             }
 30         }
 31     }
 32     for(int i=0;i<n;++i){
 33         a[x].L[i]=Find(a[l].L[i]);
 34         a[x].R[i]=Find(a[r].R[i]);
 35     }
 36 }
 37 void build(int x,int l,int r){
 38     if(l==r){
 39         a[x].num=1;
 40         a[x].L[0]=a[x].R[0]=++tot;
 41         for(int i=1;i<n;++i){
 42             if(mp[i][r]==mp[i-1][r]){
 43                 a[x].L[i]=a[x].R[i]=tot;
 44             }else{
 45                 tot++,a[x].num++;
 46                 a[x].L[i]=a[x].R[i]=tot;
 47             }
 48         }
 49         return;
 50     }
 51     int mid=(l+r)>>1;
 52     build(lson);
 53     build(rson);
 54     push_up(x,mid);
 55 }
 56 void query(int x,int l,int r,int ql,int qr){
 57     if(ql<=l&&r<=qr){
 58         if(flag){
 59             flag=0;
 60             ans=a[x];
 61             return;
 62         }else{
 63             ans.num+=a[x].num;
 64             for(int i=0;i<n;++i){
 65                 pre[ans.R[i]]=ans.R[i];
 66                 pre[a[x].L[i]]=a[x].L[i];
 67                 pre[a[x].R[i]]=a[x].R[i];
 68             }
 69             for(int i=0;i<n;++i){
 70                 if(mp[i][l-1]==mp[i][l]){
 71                     if(Find(ans.R[i])!=Find(a[x].L[i])){
 72                         ans.num--;
 73                         Union(ans.R[i],a[x].L[i]);
 74                     }
 75                 }
 76             }
 77             for(int i=0;i<n;++i)
 78                 ans.R[i]=Find(a[x].R[i]);
 79             return;
 80         }
 81     }
 82     int mid=(l+r)>>1;
 83     if(ql<=mid)query(lson,ql,qr);
 84     if(mid<qr)query(rson,ql,qr);
 85 }
 86 int main(void){
 87     scanf("%d%d%d",&n,&m,&q);
 88     init(n*m);
 89     for(int i=0;i<n;++i)
 90         for(int j=0;j<m;++j)
 91             scanf("%d",&mp[i][j]);
 92     build(1,0,m-1);
 93     while(q--){
 94         int x,y;
 95         scanf("%d%d",&x,&y);x--;y--;
 96         flag=1;
 97         query(1,0,m-1,x,y);
 98         printf("%d
",ans.num);
 99     }
100 }
View Code
原文地址:https://www.cnblogs.com/barrier/p/6914277.html