• Codeforces Global Round 1 做题记录


    A.

    题解:快速幂

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define maxn 100005
     4 using namespace std;
     5 const ll mod=2;
     6 ll b,k;
     7 ll a[maxn];
     8 ll fastpow(ll a,ll p)
     9 {
    10     ll ans=1;
    11     while(p)
    12     {
    13         if(p&1)ans=ans*a%mod;
    14         a=a*a%mod;p>>=1;
    15     }
    16     return ans;
    17 }
    18 int main()
    19 {
    20     scanf("%I64d%I64d",&b,&k);
    21     for(int i=1;i<=k;++i)scanf("%I64d",&a[i]);
    22     ll n=0;
    23     for(int i=1;i<=k;++i)n=(n+a[i]*fastpow(b,k-i)%mod)%mod;
    24     if(n)puts("odd");
    25     else puts("even");
    26 }
    View Code

    B.

    题解:考虑两两相邻点之间的距离,贪心取最小的k-1个

     1 #include<bits/stdc++.h>
     2 #define maxn 100005
     3 using namespace std;
     4 int n,m,k;
     5 int a[maxn];
     6 priority_queue<int,vector<int>,greater<int> >q;
     7 int main()
     8 {
     9     scanf("%d%d%d",&n,&m,&k);
    10     int ans=n;
    11     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    12     k=n-k;
    13     for(int i=1;i<n;++i)q.push(a[i+1]-a[i]-1);
    14     while(k--)
    15     {
    16         int t=q.top();
    17         q.pop();
    18         ans+=t;
    19     }
    20     printf("%d
    ",ans);
    21     return 0;
    22 }
    View Code

    C.

    题解:找规律,除了2^k-1以外其他情况ans=2^p-1(其中p为满足ans>a的最小的数),2^k-1的情况打表就行

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int q;
     4 int vis[]={0,0,1,1,5,1,21,1,85,73,341,89,1365,1,5461,4681,21845,1,87381,1,349525,299593,1398101,178481,5592405,1082401};
     5 int main()
     6 {
     7     scanf("%d",&q);
     8     while(q--)
     9     {
    10         int a;
    11         scanf("%d",&a);
    12         int p=1;
    13         while(((1<<p)-1)<a)p++;
    14         if(a==((1<<p)-1))
    15         {
    16             if(!vis[p])
    17             {
    18                 int ans=0;
    19                 for(int b=1;b<a;++b)ans=max(ans,__gcd(a^b,a&b));
    20                 vis[p]=ans;
    21                 printf("%d
    ",ans);
    22             }
    23             else printf("%d
    ",vis[p]);
    24         }
    25         else printf("%d
    ",(1<<p)-1);
    26     }
    27     return 0;
    28 }
    View Code

    D.

    题解:考虑3个三元组[ i-1 ,i ,i+1 ]可以被拆成[ i-1, i-1, i-1 ] , [ i , i , i ] , [ i+1, i+1, i+1 ],所以每个状态中这样的三元组不会超过2个

    然后dp(i,j,k)表示有j个[ i-1 ,i ,i+1 ] , k个[ i , i+1 , i+2 ],转移每次枚举一个 l ,表示dp(i+1,k,l),其中多l个[ i+1 , i+2, i+3 ]

    那相同的三元组怎么处理?( num(i) - j -k -l )/3 个,直接加上就好了

     1 #include<bits/stdc++.h>
     2 #define inf 1000000000
     3 #define maxn 1000005
     4 using namespace std;
     5 int n,m;
     6 int has[maxn];
     7 int dp[maxn][3][3];
     8 int main()
     9 {
    10     scanf("%d%d",&n,&m);
    11     for(int x,i=1;i<=n;++i)
    12     {
    13         scanf("%d",&x);
    14         has[x]++;
    15     }
    16     for(int i=0;i<=m;++i)
    17     {
    18         for(int j=0;j<=2;++j)
    19         {
    20             for(int k=0;k<=2;++k)dp[i][j][k]=-inf;
    21         }
    22     }
    23     dp[0][0][0]=0;
    24     for(int i=0;i<m;++i)
    25     {
    26         for(int j=0;j<=min(has[i],2);++j)
    27         {
    28             for(int k=0;k<=min(has[i+1],2);++k)
    29             {
    30                 for(int l=0;l<=min(has[i+2],2);++l)if(has[i+1]>=j+k+l)
    31                 {
    32                     dp[i+1][k][l]=max(dp[i+1][k][l],dp[i][j][k]+l+(has[i+1]-j-k-l)/3);
    33                 }
    34             }
    35         }
    36     }
    37     printf("%d
    ",dp[m][0][0]);
    38     return 0;
    39 }
    View Code

    E.

    题解:原题,以前有一道前缀和类似的结论

    考虑每次操作,本质上是在差分数组中交换两个数的位置

    我们只需要判断差分数组是否同构以及原数组首尾是否相同就行了

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define maxn 100005
     4 using namespace std;
     5 int n;
     6 ll c[maxn],t[maxn],x[maxn],y[maxn]; 
     7 int main()
     8 {
     9     scanf("%d",&n);
    10     for(int i=1;i<=n;++i)scanf("%I64d",&c[i]);
    11     for(int i=1;i<=n;++i)scanf("%I64d",&t[i]);
    12     if(c[1]!=t[1]||c[n]!=t[n])
    13     {
    14         puts("No");
    15         return 0;
    16     }
    17     else
    18     {
    19         for(int i=2;i<=n;++i)x[i]=c[i]-c[i-1];
    20         for(int i=2;i<=n;++i)y[i]=t[i]-t[i-1];
    21         sort(x+1,x+n+1);
    22         sort(y+1,y+n+1);
    23         bool yes=1;
    24         for(int i=1;i<=n;++i)if(x[i]!=y[i])yes=0;
    25         if(yes)puts("Yes");
    26         else puts("No");
    27     }
    28     return 0; 
    29 }
    View Code

    F.

    题解:离线询问,线段树维护dfs序,查询相当于区间min,每次转移一条边相当于区间add

      1 #include<bits/stdc++.h>
      2 #define ll long long
      3 #define maxn 500005
      4 using namespace std;
      5 const ll inf = (ll)1e17;
      6 int n,q;
      7 int fa[maxn];
      8 ll ww[maxn];
      9 struct edge
     10 {
     11     int to,next;
     12     ll w;
     13 }e[maxn];
     14 int head[maxn],p;
     15 void addedge(int u,int v,ll w)
     16 {
     17     e[++p].to=v;e[p].w=w;e[p].next=head[u];head[u]=p;
     18 }
     19 struct Query
     20 {
     21     int v,l,r,id;
     22     Query(){};
     23     Query(int V,int L,int R,int ID){v=V;l=L;r=R;id=ID;} 
     24 };
     25 ll Ans[maxn];
     26 vector<Query> Q[maxn];
     27 struct Segmenttree
     28 {
     29     ll minv[maxn<<2],addv[maxn<<2];
     30     void pushup(int rt)
     31     {
     32         minv[rt]=min(minv[rt<<1],minv[rt<<1|1]);
     33     }
     34     void pushdown(int rt)
     35     {
     36         if(addv[rt])
     37         {
     38             ll t=addv[rt];
     39             minv[rt<<1]+=t;minv[rt<<1|1]+=t;
     40             addv[rt<<1]+=t;addv[rt<<1|1]+=t;
     41             addv[rt]=0;
     42         }
     43     }
     44     void update(int rt,int l,int r,int pos,ll w)
     45     {
     46         int mid=(l+r)>>1;
     47         if(l==r)
     48         {
     49             addv[rt]=0;minv[rt]=w;
     50             return;
     51         }
     52         if(pos<=mid)update(rt<<1,l,mid,pos,w);
     53         else update(rt<<1|1,mid+1,r,pos,w);
     54         pushup(rt);
     55     }
     56     void add(int rt,int l,int r,int ql,int qr,ll w)
     57     {
     58         if(ql>qr)return;
     59         int mid=(l+r)>>1;
     60         if(ql<=l&&r<=qr)
     61         {
     62             addv[rt]+=w;minv[rt]+=w;
     63             return;
     64         }
     65         pushdown(rt);
     66         if(ql<=mid)add(rt<<1,l,mid,ql,qr,w);
     67         if(qr>mid)add(rt<<1|1,mid+1,r,ql,qr,w);
     68         pushup(rt);
     69     }
     70     ll query(int rt,int l,int r,int ql,int qr)
     71     {
     72         ll ans=inf;
     73         int mid=(l+r)>>1;
     74         if(ql<=l&&r<=qr)return minv[rt];
     75         pushdown(rt);
     76         if(ql<=mid)ans=min(ans,query(rt<<1,l,mid,ql,qr));
     77         if(qr>mid)ans=min(ans,query(rt<<1|1,mid+1,r,ql,qr));
     78         pushup(rt);
     79         return ans;
     80     }
     81 }sgt;
     82 int size[maxn],lpos[maxn],rpos[maxn],cnt;
     83 ll dis[maxn];
     84 void dfs(int u)
     85 {
     86     size[u]=1;
     87     lpos[u]=++cnt;
     88     for(int i=head[u];i;i=e[i].next)
     89     {
     90         int v=e[i].to;ll w=e[i].w;
     91         dis[v]=dis[u]+w;
     92         dfs(v);
     93         size[u]+=size[v];
     94     }
     95     rpos[u]=cnt;
     96     if(size[u]==1)sgt.update(1,1,n,lpos[u],dis[u]);
     97     else sgt.update(1,1,n,lpos[u],inf);
     98 }
     99 void dfs2(int u)
    100 {
    101     for(int i=0;i<Q[u].size();++i)
    102     {
    103         int id=Q[u][i].id,l=Q[u][i].l,r=Q[u][i].r;
    104         Ans[id]=sgt.query(1,1,n,l,r);
    105     }
    106     for(int i=head[u];i;i=e[i].next)
    107     {
    108         int v=e[i].to;ll w=e[i].w;
    109         sgt.add(1,1,n,lpos[v],rpos[v],-w);
    110         sgt.add(1,1,n,1,lpos[v]-1,w);
    111         sgt.add(1,1,n,rpos[v]+1,n,w);
    112         dfs2(v);
    113         sgt.add(1,1,n,lpos[v],rpos[v],w);
    114         sgt.add(1,1,n,1,lpos[v]-1,-w);
    115         sgt.add(1,1,n,rpos[v]+1,n,-w);
    116     }
    117 }
    118 int main()
    119 {
    120     scanf("%d%d",&n,&q);
    121     for(int i=2;i<=n;++i)
    122     {
    123         int x;ll w;
    124         scanf("%d%I64d",&x,&w);
    125         fa[i]=x;ww[i]=w;
    126     }
    127     for(int i=n;i>=2;--i)addedge(fa[i],i,ww[i]);
    128     for(int i=1;i<=q;++i)
    129     {
    130         int v,l,r;
    131         scanf("%d%d%d",&v,&l,&r);
    132         Q[v].push_back(Query(v,l,r,i));
    133     }
    134     dfs(1);
    135     dfs2(1);
    136     for(int i=1;i<=q;++i)printf("%I64d
    ",Ans[i]);
    137     return 0;
    138 }
    View Code

    G.

    题解:

    大讨论博弈,细节巨多,而且操作有点强;

    先考虑一开始没有白点的情况:

    记d[u]为点u的度数

    (一)若存在u,d[u]>=4,显然白的赢;(因为白色取了这个点,那么再任意取两个相邻点就可以)

    (二)若任意u,d[u]<=2,则为一条链,显然平局;

    (三)若存在u,d[u]==3;

      (1)存在这样的u,d[u]==3且相邻三个点中度数有两个>1,那么一定是白的赢(白的选这个点,黑的堵一个点,白的再选一个度数>1的点,显然可以构成链)

      (2)不存在这样的u,d[u]==3且相邻三个点中有两个度数>1:

        那么一定是一条链,其中一头或两头挂着一个两分叉:

        ①一分叉:显然平局;

        ②两分叉:(这种情况有坑)

          1.链上偶数个点,白的赢;

          (白的先选一头的2号点(d[u]=3的那个点旁边的一个d[u]=2的点),然后黑的必须堵1号点(就是d[u]=3的那个点),

          然后白的选4号点,黑的堵3号点,……,白的选2n号点,黑的堵2n-1号点,然后白的选2n+1号点,白的赢了)

          2.链上奇数个点,显然平局;

    下面考虑一开始的白色点怎么处理:

    这个操作有点强,把一个白点变换为一个未涂色的点1下面挂着一个点2,点2下面挂着两个叶子点3点4;

    考虑为什么是对的:黑的和白的显然最优策略下都不能在这4个点中连成链,而且这4个点只有点1和外界相连;

             那么白的最优策略显然就是选1,达到了与白点等价的效果;

     1 #include<bits/stdc++.h>
     2 #define maxn 500005
     3 using namespace std;
     4 int T,n;
     5 struct edge
     6 {
     7     int to,next;
     8 }e[maxn*8];
     9 int head[maxn*4],p;
    10 void addedge(int u,int v)
    11 {
    12     e[++p].to=v;e[p].next=head[u];head[u]=p;
    13     e[++p].to=u;e[p].next=head[v];head[v]=p;
    14 }
    15 char col[maxn*4];
    16 int d[maxn*4];
    17 int has[5];
    18 int main()
    19 {
    20     scanf("%d",&T);
    21     while(T--)
    22     {
    23         scanf("%d",&n);
    24         p=0;
    25         for(int i=1;i<=n*4;++i)head[i]=0,d[i]=0,col[i]=0;
    26         memset(has,0,sizeof(has));
    27         for(int i=1;i<n;++i)
    28         {
    29             int u,v;
    30             scanf("%d%d",&u,&v);
    31             d[u]++;d[v]++;
    32             addedge(u,v);
    33         }
    34         scanf("%s",col+1);
    35         int cnt=n;
    36         for(int i=1;i<=n;++i)if(col[i]=='W')
    37         {
    38             d[i]++;
    39             d[++cnt]=3;
    40             addedge(i,cnt);
    41             d[++cnt]=1;
    42             addedge(cnt-1,cnt);
    43             d[++cnt]=1;
    44             addedge(cnt-2,cnt);
    45         }
    46         n=cnt;
    47         for(int i=1;i<=n;++i)has[min(d[i],4)]++;
    48         if(has[4])puts("White");
    49         else if(has[3])
    50         {
    51             bool yes=0;
    52             for(int u=1;u<=n;++u)if(d[u]==3)
    53             {
    54                 int num=0;
    55                 for(int i=head[u];i;i=e[i].next)
    56                 {
    57                     int v=e[i].to;
    58                     if(d[v]>1)num++;
    59                 }
    60                 if(num>=2)yes=1;
    61             }
    62             if(yes)puts("White");
    63             else
    64             {
    65                 if(has[3]==2)
    66                 {
    67                     if(n&1)puts("White");
    68                     else puts("Draw");
    69                 }
    70                 else puts("Draw");
    71             }
    72         }
    73         else puts("Draw");
    74     }
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    二叉树中序遍历及后序遍历(下)
    完全二叉树和三序遍历算法(先序)(上)
    分布式调度——zookeeper
    Linux版JDK环境安装
    Redis的事务
    Redis的持久化——RDB与AOF
    分布式缓存——Redis
    非关系型数据库
    分布式存储——MySQL
    分布式系统
  • 原文地址:https://www.cnblogs.com/uuzlove/p/10358689.html
Copyright © 2020-2023  润新知