Codeforces Round #378 (Div. 2)

http://codeforces.com/contest/733

A. Grasshopper And the String
其实就是统计最长连续的非元音字符长度,+1输出

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 100005;
typedef long long int ll;
char s[120];
int main()
{
    scanf("%s",s);
    int len = strlen(s);
    int ans = 0,con=0;
    for(int i=0;i<len;++i)
    {
        if(s[i]!='A' && s[i]!='E' && s[i]!='I' && s[i]!='O' && s[i]!='U' && s[i]!='Y')
        con++;
        else {
            ans = max(ans,con);
            con=0;
        }   
    }
    ans = max(ans,con);
    printf("%d\n",ans+1);
    return 0;
}

B. Parade
思路很简单,检查左右大小的一致性,左恒大于等于右,或者右恒大于等于左,就输出0,否则就输出相减绝对值最大的列数,左大于右输正最大,右大于左输负数里面绝对值最大的,注意输出的是列数

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100005;
typedef long long int ll;
int a[maxn][3];
int main()
{
    int n;
    scanf("%d",&n);
    ll  lef = 0,rig = 0,f=1,r=1;
    for(int i=0;i<n;++i)
    {
        scanf("%d %d",&a[i][0],&a[i][1]);
        a[i][2]=a[i][1] - a[i][0];
        if(a[i][2]<0)f=0;//全部右边大于左边 
        if(a[i][2]>0)r=0;   
        lef+=a[i][0];
        rig+=a[i][1];       
    }
    if(f || r){
        printf("0\n");
        return 0;
    } 

    ll ma = abs(lef-rig);
    int ans = 0;
    if(lef != rig){
        int mt = 0,p=0,q=0,mi=0;
        for(int i=0;i<n;++i)
        {
            if(a[i][2]>mt){//正数最大 
                mt=a[i][2];
                p=i;
            }
            if(a[i][2]<mi){//负数最小 
                mi=a[i][2];
                q=i;
            }
        }
        ll tlef = lef-a[p][0]+a[p][1],trig =rig-a[p][1]+a[p][0];
        ll tma = abs(tlef-trig);

        if(tma>ma){
            ans=p;
            ma=tma;
        }

        tlef = lef-a[q][0]+a[q][1];trig =rig-a[q][1]+a[q][0];
        tma = abs(tlef-trig);
        if(tma>ma){
            ans=q;
            ma=tma;
        }

        printf("%d\n",ans+1);
    }else {
        int mt = abs(a[0][2]),p=0;
        for(int i=0;i<n;++i)
        {
            if(abs(a[i][2])>mt){
                mt=abs(a[i][2]);
                p=i;
            }
        }
        printf("%d\n",p+1);
    }
    return 0;
}

C. Epidemic in Monstropolis
打的时候没做出来,估计是没考虑 3 3 1 或 1 3 3这种情况了,还奇思妙想的想过是否全部区间和都满足的情况下还多出几只怪兽,然后等这几只怪兽看完病就会符合了,后来看数据发现并没有这种可能。
思路:首先检查某一连续区间的和是否等于b[i],看是否全部满足,
满足之后检查每一段区间的值是否一致,一致的话吃不动,不一致的话找最大值,遇到多个最大值的情况需要判断从哪只开始吃,所以位置的判断很重要,自己画图推导一下就可以了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long int ll;
const int maxn = 505;
int a[maxn],b[maxn],n,k,tot,num[maxn];
int suma[maxn],sumb[maxn];
char dire[maxn];
bool solve(int l,int r,int k)
{
    if(l==r)return 1;
    int maxv=0,pos=-1;
    for(int i=l;i<=r;++i)maxv=max(maxv,a[i]);
    for(int i=l;i<=r;++i){
        if(a[i]== maxv && ((i!=l && a[i]>a[i-1])||(i!=r && a[i]>a[i+1]))){//133 331,找开始吃的位置 
            pos=i;
            break;
        }
    }
    if(pos==-1)return 0;
    if(pos!=l && a[pos]>a[pos-1])//默认先吃左边 ,不是真的吃,pos不移动 
    {
        for(int i=pos;i>l;--i)
        {
            num[++tot]=i-l+k;// pos-L是距离,+1是以L开始算pos的下标,前有k-1个数,(pos-L + 1) + k-1; 
            dire[tot]='L';
        }
        for(int i=pos;i<r;++i)
        {
            num[++tot]=k; //吃完了左边,下标就一直是k 
            dire[tot]='R'; 
        }       
    }else {//否则先吃右边 
        for(int i=pos;i<r;++i)
        {
            num[++tot]=pos-l+k;//向右吃位置一直是pospos-L是距离,+1是以L开始算pos的下标,前有k-1个数,所以是(pos - L + 1) +k-1 
            dire[tot]='R'; 
        }       
        for(int i=pos;i>l;--i)
        {
            num[++tot]=i-l+k;// 吃完右边了,(pos - L +1) + k-1; 
            dire[tot]='L'; 
        }

    }
    return 1;   
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i){scanf("%d",&a[i]);suma[i]=suma[i-1]+a[i];}
    scanf("%d",&k);
    for(int i=1;i<=k;++i){scanf("%d",&b[i]);sumb[i]=sumb[i-1]+b[i];}
    if(suma[n]!=sumb[k]){
        printf("NO\n");return 0;
    }
    int pre = 0;
    for(int i=1;i<=k;++i){
        int found = 0;
        for(int j=1;j<=n;++j){
            if(suma[j]==sumb[i]){
                found = 1;

//a[pre+1] ~ a[j]区间是否存在一种情况使得最后剩下一只怪兽且体重为 b[i]
                if(!solve(pre+1,j,i))
                {
                    printf("NO\n");
                    return 0;
                }
                pre=j;
            }   
        }
        if(!found){
            printf("NO\n");
            return 0;
        }
    }
    printf("YES\n");
    for(int i=1;i<=n-k;++i)
    printf("%d %c\n",num[i],dire[i]);
    return 0;
}

D. Kostya the Sculptor

思路很简单,因为限制半径的是最短的边,所以输入的时候a存最长的,c存最短的边就好,因为只能最多选两个长方体,而我们知道两个长方体合起来最多只能改变一个变量,就是改变最短的那条边或者不匹配的那条边,比如12 6 6 ,6 6 6会变成18 6 6,所以存起来排个序,排序后判断相邻的两个长方体是否至少有两条边相同长度,匹配的话就取min(b,c1+c2),因为最短边加起来是有可能大于次长边的,时间复杂度是0(n+nlog n),注意了不匹配的长方体是不能合起来的

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100050;
typedef long long int ll;
struct node {
    ll a,b,c;
    int d;
}t[maxn];

bool cmp(struct node a,struct node b)
{
    if(a.a>b.a)return 1;
    else if(a.a==b.a){
        if(a.b>b.b)return 1;
        else if(a.b==b.b){
            return a.c>=b.c?1:0;
        }
        return 0;
    }
    return 0;
}

int main()
{
    int n;
    scanf("%d",&n);
    ll cmax = 0;
    int ans=0;
    for(int i=1;i<=n;++i){
        ll aa,bb,cc;
        scanf("%lld %lld %lld",&aa,&bb,&cc);
        t[i].a = max(aa,max(bb,cc));
        t[i].c = min(aa,min(bb,cc));
        t[i].b = aa+bb+cc-t[i].a-t[i].c;
        t[i].d=i;
        if(t[i].c>cmax){
            cmax=t[i].c;
            ans=i;
        }
    }
    sort(t+1,t+n+1,cmp);

    int pick=1,one=-1,two=-1;
    for(int i=1;i<n;++i)
    {
        if(t[i].a>cmax && t[i].b>cmax){         
            int j=i+1;          
            if(t[i].a==t[j].a && t[i].b==t[j].b)
            {
                ll lest = min(t[i].b,t[i].c+t[j].c);            
                if(lest>cmax){
                    pick=2;
                    cmax = lest;
                    one = t[i].d;
                    two = t[j].d;
                }
            }   
        }   
    }
    printf("%d\n",pick);
    if(pick==1)printf("%d\n",ans);
    else printf("%d %d\n",one,two);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值