Codeforces Round #470 (rated, Div. 2, based on VK Cup 2018 Round 1) 题解

比赛链接:http://codeforces.com/contest/948
A. Protect Sheep
题意:给了一个n*m的图,其中.代表空地,S代表羊,W代表狼,D代表狗,羊和狗都不能动,只有狼可以冻,现在狗有无限多个,如果通过给地图放狗可以保护所有的羊都不被吃,那就输出放狗之后的图,如果通过放狗还可以使狼吃羊,那么就输出No。
解法:我们只需要判断每一只羊的上下左右没有狼就好,如果都没有狼,那么一定可以保护,直接在所有的羊周围放狗即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 505;
int n,m;
char maze[maxn][maxn];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
bool check(int x,int y){
    if(x>=0&&x<n&&y>=0&&y<m) return true;
    else return false;
}
int main(){
    scanf("%d%d",&n,&m);
    bool flag = true;
    for(int i=0; i<n; i++) scanf("%s", maze[i]);
    for(int i=0;i<n;i++){
        for(int j=0; j<m; j++){
            if(maze[i][j]=='S'){
                for(int k=0; k<4; k++){
                    int tx = i+dir[k][0];
                    int ty = j+dir[k][1];
                    if(check(tx,ty)&&maze[tx][ty]=='W'){
                        flag = false;
                    }
                }
            }
        }
    }
    if(flag){
        puts("Yes");
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
               if(maze[i][j]=='S'){
                for(int k=0;k<4;k++){
                    int tx=i+dir[k][0];
                    int ty=j+dir[k][1];
                    if(check(tx,ty)&&maze[tx][ty]=='.'){
                        maze[tx][ty]='D';
                    }
                }
               }
            }
        }
        for(int i=0;i<n;i++){
            printf("%s\n",maze[i]);
        }
    }else{
        puts("No");
    }
}

B. Primal Sport
题意:假设当前的数是x[i],那么x[i+1]由质数p(p

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
int n, ans, f[maxn];
int main(){
    scanf("%d",&n);
    ans = n;
    for(int i=2; i<=n; i++){
        if(!f[i]){
            for(int j=2*i; j<=n; j+=i) f[j] = i;
        }
        f[i] = i-f[i]+1;
    }
    for(int i=f[n];i<=n;i++) ans = min(ans, f[i]);
    printf("%d\n", ans);
}

C. Producing Snow
题意:每天会有 ai 个雪球被创建 每天会有bi 个雪球会被融化掉 求每天的融化的 个数
解法:用multiset来搞。每个ai都会被插入multiset,然后根据融化bi的累加值来判断multiset的哪些元素会被全部删除,然后删除之后再更新累加值,说的比较乱,希望代码可以看懂。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 100010;
multiset <LL> s;
LL a[maxn], b[maxn];
int main(){
    LL n;
    scanf("%lld", &n);
    for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
    for(int j=1; j<=n; j++) scanf("%lld", &b[j]);
    LL d = 0;
    LL add = 0;
    int k = 0;
    for(int i=1; i<=n; i++){
        s.insert(a[i]+add);
        d+=b[i];
        LL re = 0;
        while(s.size()&&*s.begin()-d<=0){
            re += *s.begin()-add;
            s.erase(s.begin());
            k++;
        }
        re += 1LL*(i-k)*b[i];
        add = d;
        printf("%lld ", re);
    }
    printf("\n");
}

D. Perfect Security
题意:可以任意打乱序列b的顺序和a挨着异或,求答案序列的字典序最小值。
解法:很水的一眼题,插入字典树,然后贪心。

#include <bits/stdc++.h>
using  namespace std;
int ch[9000010][2], num[9000010][2], a[300010], b[300010], p[300010], n, k;
void add(int u){
    int now = 0;
    for(int i=30; i>=0; i--){
        int t = (u>>i)&1;
        if(!ch[now][t]) ch[now][t]=++k;
        num[now][t]++;
        now=ch[now][t];
    }
}
int query(int u){
    int now=0,ans=0;
    for(int i=30;i>=0;i--){
        int t=(u>>i)&1;
        if(ch[now][t]&&num[now][t]) --num[now][t],now=ch[now][t];
        else --num[now][t^1], now=ch[now][t^1], ans+=(1<<i);
    }
    return ans;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d", &a[i]);
    for(int i=1;i<=n;i++) scanf("%d", &b[i]), add(b[i]);
    for(int i=1;i<=n;i++) p[i] = query(a[i]);
    for(int i=1;i<=n;i++) printf("%d ", p[i]);
}

E:Picking String
题意:给出字符串S和T,1e5个询问,每次询问S的一段区间是否能转变成T的一段区间。 转变方式:A->BC,B->AC,C->AB。AAA可以消除。
解法:不会这题啊。。http://blog.csdn.net/weixin_37517391/article/details/79550785
B > A C > A A B > A A A C > C
C > A B > A A C > A A A B > B
A > B C > B B
也就是说所有的C等价于B
由于B->AC也就是B->AB,而三个A可以消除,意思就是B前面可以有任意多个A,所以,B前面的紧贴着的A的数量我们可以忽略。
由于B->AB->BBB->ABBB->BBBBB,A->BB->ABB->BBBB也就是说,我们只要有一个A或者B就可以在这个基础上增加偶数个B。
那么问题就比较清楚了。但是T[c,d]串最后的A是一定要被S[a,b]最后的A抵消掉,因为没有操作可以生成A并且把A插入到S[a,b]的后面。
分为如下情况:
S [ a , b ] A T [ a , b ] A , 0 S [ a , b ] A T [ a , b ] A , d e l t a 2
d e l t a 2 0 S [ a , b ] B T [ c , d ] B 2 T [ c , d ] B 0 S [ a , b ] B 0 ( B B )
d e l t a 2 > 0 S [ a , b ] B T [ c , d ] B S [ a , b ] A B B A B
d e l t a 2 > 0 S [ a , b ] B T [ c , d ] B d e l t a 2 3 T

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+7;
char S[maxn], T[maxn];
int q,a,b,c,d;
int sumS[maxn], sumT[maxn];
int lastS[maxn], lastT[maxn];

int main(){
    scanf("%s %s %d", S,T,&q);
    for(int i=0; S[i]; i++){
        sumS[i+1] = sumS[i]+(S[i]=='C'||S[i]=='B');
        lastS[i+1] = lastS[i];
        if(S[i]=='B'||S[i]=='C') lastS[i+1]=i+1;
    }
    for(int i=0; T[i]; i++){
        sumT[i+1] = sumT[i]+(T[i]=='C'||T[i]=='B');
        lastT[i+1] = lastT[i];
        if(T[i]=='B'||T[i]=='C') lastT[i+1]=i+1;
    }
    while(q--){
        scanf("%d%d%d%d", &a,&b,&c,&d);
        int delta = sumT[d] - sumT[c-1] - (sumS[b]-sumS[a-1]);
        int delta2 = b-max(a-1,lastS[b]) - (d-max(c-1,lastT[d]));
        if(delta<0||delta%2!=0||delta2<0||delta2==0&&!(sumS[b]-sumS[a-1])&&delta>0){
            putchar('0');
            continue;
        }
        if(delta2==0||delta>0||delta2%3==0){
            putchar('1');
        }else{
            putchar('0');
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/just_sort/article/details/79617033