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

    Problem A  水题 水一水

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 char b[5][10],a[105];
     4 int main()
     5 {
     6     strcpy(b[0],"Danil");
     7     strcpy(b[1],"Olya");
     8     strcpy(b[2],"Slava");
     9     strcpy(b[3],"Ann");
    10     strcpy(b[4],"Nikita");
    11     scanf("%s",a);
    12     int cnt=0;
    13     int len=strlen(a);
    14     for(int i=0;i<len;i++)
    15     {
    16         for(int j=0;j<5;j++)
    17         {
    18             bool flag=false;
    19             int l=strlen(b[j]);
    20             for(int k=0;k<l && i+k<len;k++)
    21             {
    22                 if(a[i+k]!=b[j][k]) break;
    23                 if(k==l-1) flag=true;
    24             }
    25             if(flag) cnt++;
    26             if(cnt>1)
    27             {
    28                 i=len;
    29                 break;
    30             }
    31         }
    32     }
    33     if(cnt==0 || cnt>1) puts("NO");
    34     else puts("YES");
    35     return 0;
    36 }
    View Code

    Problem B 

    题目大意:给你一个由a,b组成的字符串,长度不超过5000,然后让你删除一些字符让它

    满足前一段全部都是a,中间一段全部都是b,最后一段全部都是a这种形式。

    思路:很容易想到求前缀和和后缀和,然后枚举分割点进行求最大长度,忘了只有一段

    的情况WA了一次。 还有一种做法是用dp扫一遍数组就行了,dp[ i ][ j ],表示当前i这个

    字符的状态为j ,状态为在第一段,第二段,第三段。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=5005;
     4 int a[N],b[N],r_a[N],r_b[N];
     5 char s[N];
     6 int main()
     7 {
     8     scanf("%s",s+1);
     9     int len=strlen(s+1);
    10     for(int i=1;i<=len;i++)
    11     {
    12         a[i]=a[i-1];
    13         b[i]=b[i-1];
    14         if(s[i]=='a') a[i]++;
    15         else b[i]++;
    16     }
    17     for(int i=len;i>=1;i--)
    18     {
    19         r_a[i]=r_a[i+1];
    20         r_b[i]-r_b[i+1];
    21         if(s[i+1]=='a') r_a[i]++;
    22         else r_b[i+1]++;
    23     }
    24     int ans=0;
    25     for(int i=0;i<=len;i++)
    26     {
    27         for(int j=i+1;j<=len;j++)
    28         {
    29             int cnt=0;
    30             cnt+=a[i];
    31             cnt+=r_a[j];
    32             cnt+=b[j]-b[i];
    33             ans=max(ans,cnt);
    34         }
    35     }
    36     ans=max(ans,a[len]);
    37     ans=max(ans,b[len]);
    38     printf("%d
    ",ans);
    39     return 0;
    40 }
    View Code

     dp代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=5005;
     4 char s[N];
     5 int dp[N][3];
     6 int main()
     7 {
     8     scanf("%s",s+1);
     9     int len=strlen(s+1);
    10     for(int i=1;i<=len;i++)
    11     {
    12         if(s[i]=='a')
    13         {
    14             dp[i][0]=dp[i-1][0]+1;
    15             dp[i][2]=max(dp[i-1][2],dp[i-1][1])+1;
    16             dp[i][1]=dp[i-1][1];
    17         }
    18         else
    19         {
    20             dp[i][1]=max(dp[i-1][0],dp[i-1][1])+1;
    21             dp[i][0]=dp[i-1][0];
    22             dp[i][2]=dp[i-1][2];
    23         }
    24     }
    25     int ans=max(dp[len][0],max(dp[len][1],dp[len][2]));
    26     printf("%d
    ",ans);
    27     return 0;
    28 }
    View Code

    Problem C

    题目大意:有一个1*n的图,每个点上有无数个坦克,现在你要去炸坦克,被个坦克要炸两次

    才会摧毁。一个点的坦克第一次被炸时会想两边移动,问你最少需要放几颗炸弹,和这些炸弹

    的位置。

    思路:感觉是个智商题,感觉我被碾压了,我原来想的是一路炸过去再一路炸回来,然后处理

    一下边界情况,发现错了,看了数据找到了规律,先炸一次偶数,再炸一次奇数,最后再炸一次

    偶数,后来想了想确实是最优的。。。。。。。。。。

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    int main()
    {
        vector<int> ans;
        scanf("%d",&n);
        for(int i=2;i<=n;i+=2) ans.push_back(i);
        for(int i=1;i<=n;i+=2) ans.push_back(i);
        for(int i=2;i<=n;i+=2) ans.push_back(i);
        int len=ans.size();
        printf("%d
    ",len);
        for(int i=0;i<len;i++) printf("%d ",ans[i]);
        puts("");
        return 0;
    }
    View Code

    Problem D

    题目大意:给你n*m的图和一个起点,一个终点,一个人站在起点,每次他能向上下左右一个方向

    前进k步以内,问你最少要多少步到达终点。n,m,k<=1000

    思路:我们可以很容易地想到直接一个bfs来求,但是k的值最大为1000,复杂度最坏能卡成n*m*k

    所以我就想用图的链表形式写,每访问过一个点就将这个点上边的点和下面的点相连,左边的点和

    右边的点相连,然后我们的复杂度就变成了n*m。

    ps:这个指针写的我好难受。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1005;
    struct node
    {
        char c;
        int row,col;
        node *l,*r,*x,*s;
    }w[N][N];
    char ss[3],ww[N][N];
    struct step
    {
        step(int a=0,int b=0,int c=0){ row=a; col=b; cnt=c;}
        int row,col,cnt;
    };
    step cur;
    bool vis[N][N];
    int n,m,k,x1,x2,y1,y2;
    queue<step>Q;
    void work(int i,int j)
    {
        if(w[i][j].l!=NULL && w[i][j].r!=NULL)
        {
            w[i][j].l->r=w[i][j].r;
            w[i][j].r->l=w[i][j].l;
        }
        else if(w[i][j].l!=NULL) w[i][j].l->r=NULL;
        else if(w[i][j].r!=NULL) w[i][j].r->l=NULL;
        if(w[i][j].s!=NULL && w[i][j].x!=NULL)
        {
            w[i][j].s->x=w[i][j].x;
            w[i][j].x->s=w[i][j].s;
        }
        else if(w[i][j].s!=NULL) w[i][j].s->x=NULL;
        else if(w[i][j].x!=NULL) w[i][j].x->s=NULL;
    }
    void dfs(int row,int col,int op)
    {
        if(row!=cur.row && col!=cur.col) work(row,col);
        if(op==1)
        {
            if(w[row][col].l!=NULL && cur.col-w[row][col].l->col<=k)
            {
                Q.push(step(w[row][col].l->row,w[row][col].l->col,cur.cnt+1));
                work(w[row][col].l->row,w[row][col].l->col);
                dfs(w[row][col].l->row,w[row][col].l->col,1);
                w[row][col].l=NULL;
            }
        }
        else if(op==2)
        {
            if(w[row][col].r!=NULL && w[row][col].r->col-cur.col<=k)
            {
                Q.push(step(w[row][col].r->row,w[row][col].r->col,cur.cnt+1));
                work(w[row][col].r->row,w[row][col].r->col);
                dfs(w[row][col].r->row,w[row][col].r->col,2);
                w[row][col].r=NULL;
            }
        }
        else if(op==3)
        {
            if(w[row][col].s!=NULL && cur.row-w[row][col].s->row<=k)
            {
                Q.push(step(w[row][col].s->row,w[row][col].s->col,cur.cnt+1));
                work(w[row][col].s->row,w[row][col].s->col);
                dfs(w[row][col].s->row,w[row][col].s->col,3);
                w[row][col].s=NULL;
            }
        }
        else if(op==4)
        {
            if(w[row][col].x!=NULL && w[row][col].x->row-cur.row<=k)
            {
                Q.push(step(w[row][col].x->row,w[row][col].x->col,cur.cnt+1));
                work(w[row][col].x->row,w[row][col].x->col);
                dfs(w[row][col].x->row,w[row][col].x->col,4);
                w[row][col].x=NULL;
            }
        }
    }
    int main()
    {
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++) scanf("%s",ww[i]+1);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m; j++)
            {
                w[i][j].c=ww[i][j];
                w[i][j].row=i;
                w[i][j].col=j;
            }
        }
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                if(i-1>0 && w[i-1][j].c!='#') w[i][j].s=&w[i-1][j];
                else w[i][j].s=NULL;
                if(i+1<=n && w[i+1][j].c!='#') w[i][j].x=&w[i+1][j];
                else w[i][j].x=NULL;
                if(j-1>0 && w[i][j-1].c!='#') w[i][j].l=&w[i][j-1];
                else w[i][j].l=NULL;
                if(j+1<=m && w[i][j+1].c!='#') w[i][j].r=&w[i][j+1];
                else w[i][j].r=NULL;
            }
        }
        work(x1,y1);
        Q.push(step(x1,y1,0));
        while(!Q.empty())
        {
            cur=Q.front(); Q.pop();
            if(cur.row==x2 && cur.col==y2)
            {
                printf("%d
    ",cur.cnt);
                return 0;
            }
            dfs(cur.row,cur.col,1);
            dfs(cur.row,cur.col,2);
            dfs(cur.row,cur.col,3);
            dfs(cur.row,cur.col,4);
        }
        puts("-1");
        return 0;
    }
    View Code

    Problem E

    题目大意:给你一棵以 1 为根节点的树,每个节点代表的值是1或者0,然后有q个有两种操作,

    一种操作是询问一棵子树里1的个数,另一种操作是将一棵子树的值翻转。

    思路:想了一会就想出来了,以前好像写过类似的题,用dfs序将每棵子树转换成一个区间,

    然后就变成了 RMQ问题,用线段树就好了,push_down里面写搓了一次,不能直接将左子树

    和右子树的lazy变成1,要让它们++ 再对2 取模。

     1 #include<bits/stdc++.h>
     2 #define lson l,m,rt<<1
     3 #define rson m+1,r,rt<<1|1
     4 using namespace std;
     5 const int N=2*1e5+5;
     6 int lazy[N<<2],seg[N<<2],n,s[N],e[N],tot,a[N],b[N];
     7 vector<int> E[N];
     8 void build(int l,int r,int rt)
     9 {
    10     if(l==r)
    11     {
    12         if(a[l]==1) seg[rt]=1;
    13         return;
    14     }
    15     int m=(l+r)>>1;
    16     build(lson);
    17     build(rson);
    18     seg[rt]=seg[rt<<1]+seg[rt<<1|1];
    19 }
    20 void dfs(int v)
    21 {
    22     int len=E[v].size();
    23     s[v]=++tot;
    24     for(int i=0;i<len;i++)
    25     {
    26         int to=E[v][i];
    27         dfs(to);
    28     }
    29     e[v]=tot;
    30 }
    31 void push_down(int rt,int l,int r)
    32 {
    33     if(!lazy[rt]) return;
    34     lazy[rt]=0;
    35     int m=(l+r)>>1;
    36     seg[rt<<1]=m-l+1-seg[rt<<1];
    37     seg[rt<<1|1]=r-m-seg[rt<<1|1];
    38     lazy[rt<<1]++; lazy[rt<<1|1]++;
    39     lazy[rt<<1]%=2; lazy[rt<<1|1]%=2;
    40 }
    41 void update(int L,int R,int l,int r,int rt)
    42 {
    43     if(l>=L && r<=R)
    44     {
    45         seg[rt]=r-l+1-seg[rt];
    46         lazy[rt]++; lazy[rt]%=2;
    47         return;
    48     }
    49     int m=(l+r)>>1;
    50     push_down(rt,l,r);
    51     if(L<=m) update(L,R,lson);
    52     if(R>m) update(L,R,rson);
    53     seg[rt]=seg[rt<<1]+seg[rt<<1|1];
    54 }
    55 int query(int L,int R,int l,int r,int rt)
    56 {
    57     if(l>=L && r<=R) return seg[rt];
    58     int m=(l+r)>>1;
    59     push_down(rt,l,r);
    60     int ans=0;
    61     if(L<=m) ans+=query(L,R,lson);
    62     if(R>m) ans+=query(L,R,rson);
    63     return ans;
    64 }
    65 int main()
    66 {
    67     scanf("%d",&n);
    68     for(int i=2;i<=n;i++)
    69     {
    70         int f; scanf("%d",&f);
    71         E[f].push_back(i);
    72     }
    73     for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    74     dfs(1);
    75     for(int i=1;i<=n;i++) if(b[i]) a[s[i]]=1;
    76     build(1,n,1);
    77     int q; scanf("%d",&q);
    78     while(q--)
    79     {
    80         char ss[5];
    81         int g;
    82         scanf("%s%d",ss,&g);
    83         if(ss[0]=='g') printf("%d
    ",query(s[g],e[g],1,n,1));
    84         else update(s[g],e[g],1,n,1);
    85     }
    86     return 0;
    87 }
    View Code
  • 相关阅读:
    安装wamp的方法及过程
    js原生获取className&多选一
    构造函数
    轮播图
    NaN
    ++与--运算练习
    if语句的练习
    switch语句的练习
    九九乘法表
    mac下git提交github代码
  • 原文地址:https://www.cnblogs.com/CJLHY/p/7737643.html
Copyright © 2011-2022 走看看