【BZOJ】2217-[Poi2011]Lollipop-妙


题解

一番研究发现:
我们可以先找出可以表示出的值最大的奇数和偶数。
那么小于等于该数的所有奇数/偶数均可以表示出来。
一个简单的说明:
假设现在表示出的最大偶数为n(n>=4)(n=2就只有一个2,没法表示其它的了QAQ),可以表示的范围为l-r,那么考虑三种情况:
1.两端均为2,那么任意移动一端向内一格
2.一端为2,一端为1,移动为2的一端向内一格
3.两端均为1,那么两端都向内移动一格
这样操作直到区间长度为1,达到表示的最小的1或2。
所以对询问降序排序一波,离线处理就好了。
妙啊,本蒟蒻没有想到QWQ


代码

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
const int N=1e6+10;
char s[N];
int n,m,a[N],even,odd,st,ed,sum;
int le,re,lo,ro,ansl[N],ansr[N];
struct P{int id,v;}t[N];
bool cmp(const P&x,const P&y){return x.v>y.v;}

inline int rd()
{
    char ch=getchar();int x=0,f=1;
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
    return x*f;
}

inline void mk()
{
    if(sum&1){ 
      lo=1;ro=n;
      odd=sum;
      if(st==ed && st){
         if(st-1 > n-st){
            even=2*(st-1);
            le=1;re=st-1;
         }else{
            even=2*(n-st);
            le=st+1;re=n;
         }
      }else if(st){
         if(st-1 < n-ed){
            even=sum-(2*(st-1)+1);
            le=st+1;re=n;
         }else{
            even=sum-(2*(n-ed)+1);
            le=1;re=ed-1;
         }
      }
    }else{
       even=sum;
       le=1;re=n;
       if(st){
         if(st-1 < n-ed){
            odd=sum-(2*(st-1)+1);
            lo=st+1;ro=n;
         }else{
            odd=sum-(2*(n-ed)+1);
            lo=1;ro=ed-1;
         }
       }    
    }
}

int main(){
    int i,j;n=rd();m=rd();
    scanf("%s",s+1);
    for(i=1;i<=n;++i) {
      a[i]= s[i]=='W'? 1:2; 
      sum+=a[i];
      if(a[i]==1) !st? ed=st=i:ed=i;
    }
    mk();
    for(i=1;i<=m;++i) t[i].v=rd(),t[i].id=i;
    sort(t+1,t+m+1,cmp);
    for(i=1;i<=m;++i){//n->m
        if(t[i].v&1 && (!lo || t[i].v>odd)) ansl[t[i].id]=-1;
        else if(!(t[i].v&1) && (!le || t[i].v>even)) ansl[t[i].id]=-1;
        else if(t[i].v&1){
            while(odd>t[i].v){
                if(a[lo]==2) lo++;else if(a[ro]==2) ro--;
                else{lo++;ro--;}odd-=2;
            }
            ansl[t[i].id]=lo;ansr[t[i].id]=ro;
        }else{
            while(even>t[i].v){
                if(a[le]==2) le++;else if(a[re]==2) re--;
                else{le++;re--;}even-=2; 
            }
            ansl[t[i].id]=le;ansr[t[i].id]=re;
        }
    }
    for(i=1;i<=m;++i) ansl[i]==-1? printf("NIE\n"):printf("%d %d\n",ansl[i],ansr[i]); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值