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\n",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\n",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\n",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\n",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\n",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

 

posted @ 2017-10-26 16:46  NotNight  阅读(176)  评论(0编辑  收藏  举报