Codeforces Round #390 (Div. 2) A+B+D!

                                             A. Lesha and array splitting

     水题模拟。(0:10)

     题意:给你一个n个元素的数组,求能否把这个数组分成若干连续小段,使得每段的和不为0。如有多种解输出任意一个。

     思路:搞一个前缀和,如果这个数列的和不为0那么就直接输出一个区间左为1右为n。如果数列和为0那么找一个点前面的和不为0且后面的和也不为0,直接输出这两个区间。

int a[N],sum[N];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(sum,0,sizeof(sum));
       for(int i=1;i<=n;i++)
       {
           scanf("%d",&a[i]);
           sum[i]=sum[i-1]+a[i];
       }
       if(sum[n])
       {
           printf("YES\n");
           printf("1\n1 %d\n",n);
       }
       else
       {
           int x=0;
           for(int i=1;i<n;i++)
           {
               if(sum[i]&&(sum[n]-sum[i])!=0)
               {
                   x=i;
                   break;
               }
           }
           if(x)
           {
               printf("YES\n");
               if(x!=n) printf("2\n");
               else printf("1\n");
               printf("1 %d\n",x);
               if(x<n) printf("%d %d\n",x+1,n);
           }
           else printf("NO\n");
       }
    }
    return 0;
}



                                           B. Ilya and tic-tac-toe game

     暴力或者搜索都行。(0:45)

     题意:在4*4的棋盘上下三子棋, 只要有三个连续的就算赢。现在轮到Ilya下子了,Ilya的棋子是x。问只下一步是否能赢。

    思路:所有的情况貌似也不多,全部特判就行,不过要蛮细心的。

string str[5];
int judge(int i,int j)
{
    if((i-1)>=0&&str[i-1][j]=='x'&&(i-2)>=0&&str[i-2][j]=='x') return 1;
    if((i-1)>=0&&str[i-1][j]=='x'&&(i+1)<4&&str[i+1][j]=='x') return 1;
     if((i+1)<4&&str[i+1][j]=='x'&&(i+2)<4&&str[i+2][j]=='x') return 1;
//  printf("1\n");

    if((j-1)>=0&&str[i][j-1]=='x'&&(j+1)<4&&str[i][j+1]=='x') return 1;
    if((j-1)>=0&&str[i][j-1]=='x'&&(j-2)>=0&&str[i][j-2]=='x') return 1;
    if((j+1)<4&&str[i][j+1]=='x'&&(j+2)<4&&str[i][j+2]=='x') return 1;
//printf("2\n");

    if(i+1<4&&i-1>=0&&j-1>=0&&j+1<4&&str[i-1][j-1]==str[i+1][j+1]&&str[i-1][j-1]=='x') return 1;
    if(i+1<4&&i-1>=0&&j-1>=0&&j+1<4&&str[i+1][j-1]==str[i-1][j+1]&&str[i+1][j-1]=='x') return 1;
//printf("3\n");

    if(i-2>=0)
    {
        if(j-2>=0)
        {
            if(str[i-1][j-1]=='x'&&str[i-2][j-2]=='x') return 1;
        }
        if(j+2<4)
        {
             if(str[i-1][j+1]=='x'&&str[i-2][j+2]=='x') return 1;
        }
    }
    if(i+2<4)
    {
        if(j+2<4)
        {
              if(str[i+1][j+1]=='x'&&str[i+2][j+2]=='x') return 1;
        }
        if(j-2>=0)
        {
            if(str[i+1][j-1]=='x'&&str[i+2][j-2]=='x') return 1;
        }
    }
//    printf("4\n");
    return 0;
}
void fun()
{
    int f=1;
    for(int i=0;i<4&&f;i++)
        for(int j=0;j<4&&f;j++)
        if(str[i][j]=='.'&&judge(i,j)) f=0;
    if(!f) printf("YES\n");
    else printf("NO\n");

}
int main()
{
   for(int i=0;i<4;i++)
    cin>>str[i];
    fun();
    return 0;
}


              


                                                                  D. Fedor and coupons

      唉,好气啊,一个半小时A不出这道题。

      题意:有n种优惠券,每种有一个优惠区间,也即是说编号在l到r的商品可以受到优惠。现在要你挑出k种优惠券,使得都能用这k种优惠券的商品数量越多越好。商品都是独一无二的。

      思路:就是k个区间求交集最大范围。所有区间按左端点从小到大排序,然后用优先队列维护右端点最小值。满足k个区间并且两端点差值最大即可。

      被尺取法误导了一下,以为用RMQ求【i,i+k】区间的右端点最小值然后得出差值最大,一直WA在第5组。比完赛才知道用优先队列维护。

struct node
{
    ll l,r;
    int i;
} a[N];
int n,k;
int cmp(node a,node b)
{
    return a.l<b.l;
}
int main()
{
    while(~scanf("%d%d",&n,&k))
    {
        for(int i=1; i<=n; i++)
        {
            scanf("%I64d%I64d",&a[i].l,&a[i].r);
            a[i].i=i;
        }
        sort(a+1,a+n+1,cmp);
        ll ma=0,r=0,l=0;
        priority_queue<ll,vector<ll>,greater<ll> >que;//最小值优先;
        for(int i=1; i<=n; i++)
        {
            que.push(a[i].r);
            int siz=(int)que.size();
            if(siz>k) que.pop();
            ll len=que.top()-a[i].l+1;
//            printf("%I64d %I64d %I64d\n",a[i].l,que.top(),len);
            if(siz>=k&&len>ma)
            {
                l=a[i].l;
                r=que.top();
                ma=len;
            }
        }
        printf("%I64d\n",ma);
        if(ma)
        {
            for(int i=1; i<=n&&k; i++)
            {
                if(a[i].l<=l&&a[i].r>=r)
                {
                     printf("%d ",a[i].i);
                     k--;
                }
            }
        }
        else
        {
            for(int i=1; i<=k; i++)
                printf("%d ",i);
        }
        printf("\n");
    }
    return 0;
}



转载于:https://www.cnblogs.com/nyist-TC-LYQ/p/7208138.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值