Codeforces Round #423Div. 2 A-E题解

10 篇文章 0 订阅
5 篇文章 0 订阅

A题:水题看题目然后模拟一下就好了

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n,o,t;
    int tmp=0;
    int ans=0;
    scanf("%d%d%d",&n,&o,&t);
    while(n--)
    {
        int x;
        scanf("%d",&x);
        if(x==2)
        {
            if(t)t--;
            else ans+=2;
        }
        else
        {
            if(o)o--;
            else
            {
                if(t)
                {
                    t--;
                    tmp++;
                }
                else
                {
                    if(tmp)tmp--;
                    else ans++;
                }
            }
        }
    }
    printf("%d\n",ans);
}

B题:求长和宽那个更大然后判断这个方阵容不容的下即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
char map[105][105];
int l,r,u,d;
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        l = u = max(n,m);
        r = d = -1;
        for(int i = 0; i < n; i++)
            scanf("%s",map[i]);
        int ans = 0;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
                if(map[i][j] == 'B'){
                    l = min(l,j),r = max(r,j),u = min(u,i),d = max(d,i);
                    ans++;
                }
        if(r == -1){
            puts("1");
            continue;
        }
        int len = max(r-l+1,d-u+1);
    //  printf("%d\n",len); 
        if(n>=len && m >= len){
            printf("%d\n",len*len-ans);
        }       
        else 
            puts("-1");
    }
    return 0;
}

题解思路:路径压缩去找最右边没有被使用过的字符赋上字符即可

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int mx = 3e6+5;
int p[mx];
char s[mx];
char str[mx];
int find(int x){
    return p[x] == x?x:p[x] = find(p[x]);
}
int main(){
    int n,m,pos;
    for(int i = 0; i < mx; i++)
        p[i] = i;
    memset(s,0,sizeof(s));
    int MAXN = 0;
    scanf("%d",&n);
    while(n--){
        scanf("%s",str);
        scanf("%d",&m);
        int len = strlen(str);
        while(m--){
            scanf("%d",&pos);
            pos--;
            MAXN = max(MAXN,pos+len);
            for(int i = find(pos); i-pos<len; i = p[i] = find(i+1))
                s[i] = str[i-pos];
        }
    }
    for(int i = 0; i < MAXN; i++)
        if(s[i] == 0)
            putchar('a');
        else
            printf("%c",s[i]);
    printf("\n");
    return 0;
}

题解思路:最下面的一个1结着一个然后最后把所有的没有入度为0的点(除n外)都接到第n个接点

然后边数就是如果n%k==0 || n%k==1时n/k×2当n%k == 2时就是n/k×2+1当n%k == 0&&k ==2时就是 n/k×2-1

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int mx = 2e5+5;
bool vis[mx];
int main(){
    int n,k;
    while(scanf("%d%d",&n,&k)!=EOF){
        int ans = 0;
        memset(vis,0,sizeof(vis));
        if(n%k==2)
            ans = 1;
        else if(n%k != 1 && n%k != 0)
            ans = 2;    
        if(n%k == 0 && k == 2)
            ans--;
        int d = n/k;
        ans = ans + 2*d;
        printf("%d\n",ans);
        for(int i = 0; i < d; i++)
            for(int j = 1; j <= k&&(i+1)*k+j<=n; j++){
                vis[i*k+j] = 1;
                printf("%d %d\n",i*k+j,(i+1)*k+j);
            }
        for(int i = 1; i < n; i++)
            if(!vis[i])
                printf("%d %d\n",i,n);
    }
    return 0;
}

题解思路:因为e最长10可以把这些重叠起来叠成每1个一叠,2个。。。10,然后用树状数组维护

求第一叠到第N叠一共有几个A字符,T字符,C字符,G字符就可以了

#include<iostream> 
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mx = 1e5+5;
char s[mx],e[20];
int    sum[4][11][11][mx];
int mp[256];
int MAXN;
void add(int k,int n,int p,int m){
    for(;m <= MAXN; m += m&(-m)){
        sum[k][n][p][m]++;
    }
}
void dec(int k,int n,int p,int m){
    for(;m <= MAXN; m += m&(-m))
        sum[k][n][p][m]--;
}
int query(int k,int n,int p,int m){
    int ans = 0;
    while(m){
        ans += sum[k][n][p][m];
        m -= m&(-m);
    }
    return ans;
}
int main(){
    mp['A'] = 0;
    mp['C'] = 1;
    mp['G'] = 2;
    mp['T'] = 3;
    int n,m;
    scanf("%s",s+1);
    int len = strlen(s+1);
    for(int i = 1; i <= len; i++)
        for(int j = 1; j <= 10; j++){
            MAXN = len/j+1;
            add(mp[s[i]],j,i%j,i/j+1);
        }
    scanf("%d",&n);
    while(n--){
        int casei ;
        scanf("%d",&casei);
        if(casei == 1){
            int p;
            char c;
            scanf("%d %c",&p,&c);
            for(int i = 1; i <= 10; i++){
                MAXN = len/i+1;
                add(mp[c],i,p%i,p/i+1);
                dec(mp[s[p]],i,p%i,p/i+1);
            }
            s[p] = c;
        }
        else{
             int l,r;
             scanf("%d%d%s",&l,&r,e+1);
             int len = strlen(e+1);
             int ans = 0;
             int p1,p2;
             int s = (r-l)/len;
             for(int i = 1; i <= len; i++){
                p1 = l+i-1;
                p2 = p1+s*len;
                if(p2>r)
                    p2-=len;
                ans += query(mp[e[i]],len,p2%len,p2/len+1)-query(mp[e[i]],len,p1%len,p1/len);
             }
             printf("%d\n",ans);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值