zoukankan      html  css  js  c++  java
  • Codeforces Round #699 (Div. 2)

    A

    题目大意,给一个操作序列,问能否通过删除一些操作使你从((0,0))走向((x,y))

    只保留符号相同的操作,模拟一遍看看能不能达到给定的坐标。

    #include <bits/stdc++.h>
    #define N 1000009
    using namespace std;
    typedef long long ll;
    int x,y,n;
    char s[N];
    inline ll rd(){
      ll x=0;char c=getchar();bool f=0;
      while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
      return f?-x:x;
    }
    int main(){
       int T=rd();
       while(T--){
        x=rd();y=rd();
        scanf("%s",s+1);n=strlen(s+1);
        int cnt1=0,cnt2=0;
        for(int i=1;i<=n;++i){
            if(x<0&&s[i]=='L'){
                cnt1++;
            }
            if(x>0&&s[i]=='R'){
                cnt1++;
            }
            if(y<0&&s[i]=='D'){
                cnt2++;
            }
            if(y>0&&s[i]=='U'){
                cnt2++;
            }
        }
        if(cnt1>=abs(x)&&cnt2>=abs(y))
            printf("YES
    ");
        else printf("NO
    ");
       }
       return 0;
    }
    

    B

    垃圾模拟

    #include <bits/stdc++.h>
    #define N 1000009
    using namespace std;
    typedef long long ll;
    int n,k;
    int a[N];
    inline ll rd(){
      ll x=0;char c=getchar();bool f=0;
      while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
      return f?-x:x;
    }
    int main(){
       int T=rd();
       while(T--){
        n=rd();k=rd();
        for(int i=1;i<=n;++i)a[i]=rd();
        int bo=0;int ans=0;
        for(int i=1;i<=k;++i){
            int bm=0;
            for(int j=1;j<n;++j){
                if(a[j]>=a[j+1])continue;
                else {bm=1;a[j]++;ans=j;break;}
            }
            if(!bm){bo=1;break;}
        }
        if(bo){printf("-1
    ");}
        else printf("%d
    ",ans);
       }
       return 0;
    }
    

    C

    给定初始颜色序列和最终目标颜色序列,再给定(m)个人,每个人必须按顺序给某一个格子染上(c_i)的颜色,问是否可以染成目标序列。

    我们可以将操作序列倒着考虑,如果能够一步染成目标序列那么优先染那个,否则我们可以考虑将其染到初始序列和目标序列颜色相同的位置上,或者我们可以染到之前已经被染过的地方(因为操作是可以覆盖的)。

    当有一步不能染色或者最终没有染成目标序列时无解。

    #include <bits/stdc++.h>
    #define N 100009
    using namespace std;
    typedef long long ll;
    set<int>vec[N];
    int ans[N],a[N],b[N],c[N],rbs[N];
    int n,m;
    inline ll rd(){
      ll x=0;char c=getchar();bool f=0;
      while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
      return f?-x:x;
    }
    int main(){
       int T=rd();
       while(T--){
         n=rd();m=rd();
         for(int i=1;i<=n;++i)a[i]=rd();
         for(int i=1;i<=n;++i){
           b[i]=rd();
           if(b[i]!=a[i])vec[b[i]].insert(i);
           else rbs[b[i]]=i;
         }
         for(int i=1;i<=m;++i)c[i]=rd();
         int tg=0,bm=0;
         for(int i=m;i>=1;--i){
          if(!vec[c[i]].empty()){
            ans[i]=*vec[c[i]].begin();
            tg=ans[i];
            vec[c[i]].erase(vec[c[i]].begin());
          }
          else if(rbs[c[i]]){
            ans[i]=rbs[c[i]];tg=ans[i];
          }
          else if(tg){
            ans[i]=tg;
          }
          else bm=1;
         }
         for(int i=1;i<=n;++i)if(!vec[i].empty())bm=1;
         if(bm){printf("NO
    ");}
         else{
          printf("YES
    ");
           for(int i=1;i<=m;++i)printf("%d ",ans[i]);
          puts("");
         } 
         for(int i=1;i<=n;++i){
          vec[i].clear();rbs[i]=0;
         }
       }
       return 0;
    }
    

    D

    题目大意:给定一张(n)个点的无向图,每条边上有一个字母(a)(b),问是否存在一条长度为(m)的回文路径,并且输出方案。

    首先我们不难发现当存在点对((i,j))使得来回的路径上的字母相同,那么我们一直来回地走这条边就好了,这样一定是回文的。

    进一步的,我们还可以发现当(m)为奇数时,来回地走一条边同样也是回文的。

    当这两种情况考虑过后,我们只剩下(m)为偶数且任意点对来回的字符都是相反的情况。

    我们可以枚举(i)点,找到一组((j,k))使得((i,j)!=(i,k))这样我们可以在((i,j))之间走(m/2)步,在((i,k))之间走(m/2)步,因为对称性所以走出来的一定是回文串。

    时间复杂度(O(n^2))

    #include <bits/stdc++.h>
    #define N 1009
    using namespace std;
    typedef long long ll;
    int n,m;
    char s[N][N];
    inline ll rd(){
      ll x=0;char c=getchar();bool f=0;
      while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
      return f?-x:x;
    }
    int main(){
       int T=rd();
       while(T--){
         n=rd();m=rd();
         for(int i=1;i<=n;++i){
          scanf("%s",s[i]+1);
         }
         int tg=0;
         for(int i=1;i<=n;++i){
           for(int j=1;j<i;++j){
             if(s[i][j]==s[j][i]){
               printf("YES
    ");
               for(int k=1;k<=m+1;++k){
                if(k&1)printf("%d ",i);
                else printf("%d ",j);
               }
               puts("");
               tg=1;break;
             }
           }
           if(tg)break;
         }
          if(!tg&&(m&1)){
             printf("YES
    ");
            for(int i=1;i<=m+1;++i){
              if(i&1)printf("1 ");
              else printf("2 ");
            }
            puts("");
            tg=1;
          }
          if(!tg){
            for(int i=1;i<=n;++i){
              int pre=0,tt=0;
              for(int j=1;j<=n;++j){
                if(i==j)continue;
                if(!pre)pre=s[i][j],tt=j;
                else if(s[i][j]!=pre){
                   printf("YES
    ");
                  if((m/2)&1){
                    for(int k=1;k<=m/2;++k)
                      if(k&1)printf("%d ",tt);
                      else printf("%d ",i);
                    printf("%d ",i);
                    for(int k=1;k<=m/2;++k)
                      if(k&1)printf("%d ",j);
                      else printf("%d ",i);
                  }
                  else{
                    for(int k=1;k<=m/2;++k)
                      if(k&1)printf("%d ",i);
                      else printf("%d ",tt);
                    printf("%d ",i);
                    for(int k=1;k<=m/2;++k)
                      if(k&1)printf("%d ",j);
                      else printf("%d ",i);
                  }
                  puts("");
                  tg=1;break;
                }
              }
              if(tg)break;
            }
          }
          if(!tg)printf("NO
    ");
       }
       return 0;
    }
    

    E

    题目大意:给定一个序列,每个位置的书都有一个颜色,每次操作可以将一本书放在最后,问将序列操作成相同颜色的书放在一起最少需要几步。

    我们可以补集转化一下,问题变成求出不用移动的最大个数。

    那么我们考虑两种不用移动的颜色,对于每一种颜色我们维护出最左和最右的端点,那么如果两种颜色都不用移动,那么它们一定不能相交。

    于是变成了区间覆盖问题,用(BIT)查询即可。

    但是这样会有一点问题,就是在右边一些位置是不用移动的,于是我们可以维护一下后缀最大值,在(dp)转移的时候更新答案(具体实现还是看代码比较好)。

    #include <bits/stdc++.h>
    #define N 500009
    using namespace std;
    typedef long long ll;
    int n,m;
    int l[N],r[N],tr[N],a[N],cnt[N],mxr[N],lim[N],num[N];
    inline ll rd(){
      ll x=0;char c=getchar();bool f=0;
      while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
      return f?-x:x;
    }
    inline void add(int x,int y){
      while(x<=n)tr[x]=max(tr[x],y),x+=x&-x;
    }
    inline int query(int x){
      int ans=0;
      while(x)ans=max(ans,tr[x]),x-=x&-x;
      return ans;
    }
    int main(){
       n=rd();
       for(int i=1;i<=n;++i)a[i]=rd(),l[i]=n+1;
       int mx=0;
       for(int i=n;i>=1;--i){
        cnt[a[i]]++;
        l[a[i]]=min(l[a[i]],i);
        r[a[i]]=max(r[a[i]],i);
        mx=max(mx,cnt[a[i]]);
        mxr[i]=mx;
       }
       for(int i=1;i<=n;++i){
        num[r[i]]=cnt[i];
        lim[r[i]]=l[i];
       }
       for(int i=1;i<=n;++i)if(lim[i]){
        int nm=query(lim[i]-1)+num[i];
        mx=max(mx,nm+mxr[i+1]);
        add(i,nm);
       }
       cout<<n-mx;
       return 0;
    }
    

    F

    一个奇妙构造。

  • 相关阅读:
    (原)torch中threads的addjob函数使用方法
    (原)torch中提示Unwritable object <userdata> at <?>.callback.self.XXX.threads.__gc__
    (原)luarocks更新某个模块
    EL表达式
    leetcode 151反转单词
    括号生成
    leetcode 机器人能到达的位置
    leetcode 翻转数组
    leetcode 460 LFU缓存
    leetcode 42 接雨水
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/14380708.html
Copyright © 2011-2022 走看看