zoukankan      html  css  js  c++  java
  • XIII Open Cup named after E.V. Pankratiev. GP of Saratov

    A. Box Game

    注意到局面总数不超过$50000$,而且每次操作都会改变石子的奇偶性,因此按奇偶可以将状态建成二分图,然后求出最大匹配。

    如果状态数是偶数,那么先手必胜,策略就是每次走匹配边,那么对手不能通过匹配边走回来,因此所有匹配边你都能走掉。

    如果状态数是奇数,那么如果此时有奇数个石子,也是先手必胜,因为最后对手会遭遇怎么走都会回到以前走过的局面的困境。

    选择完先后手之后,每次按匹配边走下去即可。

    B. Circle of Stones

    首先将环倍长,破环成链,那么剩下的子串要满足相邻字符不同且首尾字符不同。

    通过双指针求出每一段极长的子串,满足相邻字符不同,设这一段长度为$len$,从$2$到$len$枚举剩下的串的长度$L$,若该子串长度为$len-L+1$的前后缀不能完全匹配,则说明存在距离为$L-1$的位置不同,也就能充当首尾,Hash判断即可。

    时间复杂度$O(n)$。

    #include<cstdio>
    #include<cstring>
    typedef long long ll;
    const int N=2000010,D=233,P=1000000009;
    int C,n,m,i,j,k,len;char a[N],ans[N];ll pow[N],f[N];
    inline ll hash(int l,int r){return((f[r]-f[l-1]*pow[r-l+1])%P+P)%P;}
    int main(){
      for(pow[0]=i=1;i<N;i++)pow[i]=pow[i-1]*D%P;
      while(~scanf("%s",a+1)){
        n=strlen(a+1);m=n+n;
        for(i=1;i<=n;i++)a[i+n]=a[i];
        for(i=1;i<=m;i++)f[i]=(f[i-1]*D+a[i])%P;
        for(i=0;i<n;i++)ans[i]='0';
        for(i=1;i<=m;i=j+1){
          for(j=i;j<m&&a[j]!=a[j+1];j++);
          len=j-i+1;
          for(k=2;k<=len&&k<=n;k++)if(hash(i,i+len-k)!=hash(j-len+k,j))ans[n-k]='1';
        }
        for(printf("Case %d: ",++C),i=0;i<n-1;i++)putchar(ans[i]);puts("1");
      }
      return 0;
    }
    

      

    C. Expression with Sets

    留坑。

    D. Heating System

    留坑。

    E. Islands

    留坑。

    F. Longest Two Graphs Common String

    设$f[i][j][0]$表示选出的路径里,第一张图中最后一个点是$i$,第二张图中最后一个点是$j$的最大长度。

    设$f[i][j][1]$表示选出的路径里,第一张图中最后一个点再往后乱走一步到了$i$,第二张图中最后一个点是$j$的最大长度。

    则对于$f[i][j][0]$,只需要枚举指向$j$的边,用$f[i][j'][1]$转移;对于$f[i][j][1]$,只需要枚举指向$i$的边,用$f[i'][j][0]$转移。

    时间复杂度$O(n(n+m))$。

    #include<cstdio>
    const int N=505,M=4010;
    int T,n1,n2,m,i,j,k,flag,ans,X,Y,q[N*N][2];
    int f[N][N][2],pre[N][N][2];
    bool v[N][N][2],vis[N][N][2];
    struct G{
      int n,g[N],v[M],nxt[M],ed;
      int i,x,y;
      char a[N];
      void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
      void init(int _n,int m){
        n=_n;
        scanf("%s",a+1);
        for(ed=0,i=1;i<=n;i++)g[i]=0;
        while(m--)scanf("%d%d",&x,&y),add(y,x);
      }
    }G1,G2;
    void dp(int x,int y,int z){
      if(vis[x][y][z])flag=1;
      if(flag)return;
      if(v[x][y][z])return;
      vis[x][y][z]=v[x][y][z]=1;
      int&t=f[x][y][z],&p=pre[x][y][z];
      t=-1,p=0;
      if(z==0){
        if(G1.a[x]==G2.a[y]){
          t=0;
          for(int i=G2.g[y];i;i=G2.nxt[i]){
            int k=G2.v[i];
            dp(x,k,z^1);
            if(f[x][k][z^1]>t)t=f[x][k][z^1],p=k;
          }
          if(~t)t++;
        }
      }else{
        for(int i=G1.g[x];i;i=G1.nxt[i]){
          int k=G1.v[i];
          dp(k,y,z^1);
          if(f[k][y][z^1]>t)t=f[k][y][z^1],p=k;
        }
      }
      vis[x][y][z]=0;
    }
    int main(){
      while(~scanf("%d%d",&n1,&m)){
        G1.init(n1,m);
        scanf("%d%d",&n2,&m);
        G2.init(n2,m);
        for(i=1;i<=n1;i++)for(j=1;j<=n2;j++)for(k=0;k<2;k++)v[i][j][k]=vis[i][j][k]=0;
        ans=flag=0;
        for(i=1;i<=n1;i++)for(j=1;j<=n2;j++){
          dp(i,j,0);
          if(f[i][j][0]>ans)ans=f[i][j][0],X=i,Y=j;
        }
        printf("Case %d: ",++T);
        if(flag)puts("-1");else{
          printf("%d
    ",ans);
          for(i=ans;i;i--){
            q[i][0]=X,q[i][1]=Y;
            Y=pre[X][Y][0];
            X=pre[X][Y][1];
          }
          for(i=1;i<=ans;i++)printf("%d%c",q[i][0],i<ans?' ':'
    ');
          for(i=1;i<=ans;i++)printf("%d%c",q[i][1],i<ans?' ':'
    ');
        }
      }
      return 0;
    }
    

      

    G. Lyndon Words

    找规律构造,可以$O(n)$生成字典序下一个,暴力生成出字典序前$r$小的所有串即可。

    时间复杂度$O(nr)$。

    H. Temperature

    状压DP。

    时间复杂度$O(n2^n)$。

    I. Editor 2

    留坑。

    J. Tourist Problem

    留坑。

    K. Ant versus Woodpecker

    显然答案就是虚树上度数$>1$的点的深度的最大值,用ETT维护dfs序并支持查询lca即可。

    时间复杂度$O((m+sum k)log n)$。

    #include<cstdio>
    #include<algorithm>
    #include<set>
    using namespace std;
    const int N=400010;
    int C,n,m,i,x,g[N],Nxt[N];
    int vis[N],a[N],dfn[N],deg[N],t,q[N];
    int id[N];
    int d[N],st[N],en[N],pre[N],nxt[N],val[N],md[N],size[N],son[N][2],f[N],tot,root;
    set<int>T;
    inline void up(int x){
      md[x]=val[x];
      size[x]=1;
      if(son[x][0]){
        if(d[md[son[x][0]]]<d[md[x]])md[x]=md[son[x][0]];
        size[x]+=size[son[x][0]];
      }
      if(son[x][1]){
        if(d[md[son[x][1]]]<d[md[x]])md[x]=md[son[x][1]];
        size[x]+=size[son[x][1]];
      }
    }
    inline void rotate(int x){
      int y=f[x],w=son[y][1]==x;
      son[y][w]=son[x][w^1];
      if(son[x][w^1])f[son[x][w^1]]=y;
      if(f[y]){
        int z=f[y];
        if(son[z][0]==y)son[z][0]=x;
        if(son[z][1]==y)son[z][1]=x;
      }
      f[x]=f[y];son[x][w^1]=y;f[y]=x;up(y);
    }
    inline void splay(int x,int w){
      while(f[x]!=w){
        int y=f[x];
        if(f[y]!=w){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
        rotate(x);
      }
      if(!w)root=x;
      up(x);
    }
    inline int getrank(int x){
      splay(x,0);
      return size[son[x][0]];
    }
    inline void addnode(int x,int y){//x father is y
      d[x]=d[y]+1;
      int z=nxt[st[y]];
      splay(st[y],0);
      splay(z,root);
      son[z][0]=++tot;
      val[tot]=x;
      f[tot]=z;
      st[x]=tot;
      id[tot]=x;
      son[st[x]][1]=++tot;
      f[tot]=st[x];
      val[tot]=y;
      en[x]=tot;
      up(tot);
      up(st[x]);
      up(z);
      up(root);
      nxt[root]=st[x];
      nxt[st[x]]=en[x];
      nxt[en[x]]=z;
      pre[z]=en[x];
      pre[en[x]]=st[x];
      pre[st[x]]=root;
    }
    void dfsdel(int x){
      if(!x)return;
      if(id[x])T.insert(id[x]);
      dfsdel(son[x][0]);
      dfsdel(son[x][1]);
    }
    inline void delsubtree(int x){
      splay(pre[st[x]],0);
      splay(nxt[en[x]],root);
      int z=son[root][1];
      nxt[root]=z;
      pre[z]=root;
      dfsdel(son[z][0]);
      son[z][0]=0;
      up(z);
      up(root);
    }
    void show(int x){
      if(!x)return;
      show(son[x][0]);
      printf("%d ",val[x]);
      show(son[x][1]);
    }
    inline int lca(int x,int y){
      if(x==y)return x;
      if(x==1||y==1)return 1;
      if(getrank(st[x])>getrank(st[y]))swap(x,y);
      splay(pre[st[x]],0);
      splay(nxt[st[y]],root);
      return md[son[son[root][1]][0]];
    }
    int build(int l,int r,int fa){
      int mid=(l+r)>>1;
      f[mid]=fa;
      if(l<mid)son[mid][0]=build(l,mid-1,mid);
      if(r>mid)son[mid][1]=build(mid+1,r,mid);
      up(mid);
      return mid;
    }
    inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
    void dfs(int x){
      for(int i=g[x];i;i=Nxt[i]){
        d[i]=d[x]+1;
        st[i]=++tot;
        val[tot]=i;
        dfs(i);
        en[i]=++tot;
        val[tot]=x;
      }
    }
    inline int getid(){
      int x=*T.begin();
      T.erase(x);
      return x;
    }
    int main(){
      while(~scanf("%d",&n)){
        st[1]=1;
        val[1]=1;
        tot=1;
        for(i=2;i<=n;i++){
          scanf("%d",&x);
          Nxt[i]=g[x];
          g[x]=i;
        }
        dfs(1);
        en[1]=++tot;
        val[tot]=1;
        for(i=1;i<tot;i++){
          pre[i+1]=i;
          nxt[i]=i+1;
        }
        for(i=1;i<=n;i++)id[st[i]]=i;
        root=build(1,tot,0);
        int mm;
        scanf("%d",&mm);
        int lim=n+mm;
        T.clear();
        for(i=n+1;i<=n+mm;i++)T.insert(i);
        int last=0;
        printf("Case %d:",++C);
        while(mm--){
          char op[5];
          scanf("%s",op);
          if(op[0]=='+'){
            int x;
            scanf("%d",&x);
            int y=getid();
            x+=last;
            addnode(y,x);
          }
          if(op[0]=='-'){
            int x;
            scanf("%d",&x);
            delsubtree(x);
          }
          if(op[0]=='?'){
            //show(root);puts("");
            scanf("%d",&m);
            int cnt=1;
            a[1]=1;
            vis[1]=1;
            dfn[1]=getrank(st[1]);
            while(m--){
              scanf("%d",&x);
              if(!vis[x]){
                a[++cnt]=x,vis[x]=1;
                dfn[x]=getrank(st[x]);
              }
            }
            //for(i=1;i<=cnt;i++)printf("%d ",a[i]);puts("");
            sort(a+1,a+cnt+1,cmp);
            int now=cnt;
            for(i=1;i<cnt;i++)if(!vis[x=lca(a[i],a[i+1])]){
              vis[a[++now]=x]=1;
              dfn[x]=getrank(st[x]);
            }
            sort(a+1,a+now+1,cmp);
            //for(i=1;i<=now;i++)printf("%d ",a[i]);puts("");
            last=-1;
            for(q[t=1]=1,i=2;i<=now;q[++t]=a[i++]){
              while(lca(a[i],q[t])!=q[t])t--;
              deg[q[t]]++;
              if(deg[q[t]]>1)last=max(last,d[q[t]]);
              //printf("edge %d %d
    ",q[t],a[i]);
            }
            printf(" %d",last);
            for(i=1;i<=now;i++)vis[a[i]]=deg[a[i]]=0;
          }
        }
        puts("");
        for(i=1;i<=lim;i++)st[i]=en[i]=d[i]=g[i]=0;
        for(i=0;i<=tot+1;i++)id[i]=pre[i]=nxt[i]=val[i]=md[i]=size[i]=son[i][0]=son[i][1]=f[i]=0;
        tot=root=0;
      }
      return 0;
    }
    

      

  • 相关阅读:
    Shiro
    RabbitMQ
    RabbitMQ
    RabbitMQ
    RabbitMQ
    RabbitMQ
    RabbitMQ
    Java
    Java
    Java
  • 原文地址:https://www.cnblogs.com/clrs97/p/5701534.html
Copyright © 2011-2022 走看看