BZOJ2217 : [Poi2011]Lollipop

若能得到一个和为t的区间,那么至少去掉两端点中任意一个后必定能得到和为t-2的区间。

所以只需要分别找到和最大的和为奇数和偶数的区间,然后$O(n)$完成构造即可。

 

#include<cstdio>
#define N 1000010
int n,m,i,s[N],b,c,d,t,l,r,f[N<<1][2];char a[N];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int main(){
  read(n),read(m),scanf("%s",a+1);
  for(i=1;i<=n;i++)a[i]=a[i]=='W'?1:2,s[i]=s[i-1]+a[i];
  for(b=1;b<=n;b++)if(s[b]&1)break;
  for(c=n;c;c--)if(s[c]&1)break;
  for(d=n;d;d--)if(!(s[d]&1))break;
  if(s[d]>t)t=s[d],l=1,r=d;
  if(s[c]-s[b]>t)t=s[c]-s[b],l=b+1,r=c;
  for(;l<=r&&t>0;t-=2){
    f[t][0]=l,f[t][1]=r;
    if(a[l]==2)l++;else if(a[r]==2)r--;else l++,r--;
  }
  t=0;
  if(s[c]>t)t=s[c],l=1,r=c;
  if(s[d]-s[b]>t)t=s[d]-s[b],l=b+1,r=d;
  for(;l<=r&&t>0;t-=2){
    f[t][0]=l,f[t][1]=r;
    if(a[l]==2)l++;else if(a[r]==2)r--;else l++,r--;
  }
  while(m--){
    read(t);
    if(f[t][0])printf("%d %d\n",f[t][0],f[t][1]);else puts("NIE");
  }
  return 0;
}

  

posted @ 2015-08-17 01:53  Claris  阅读(258)  评论(0编辑  收藏  举报