BZOJ2217 : [Poi2011]Lollipop

Claris發表於2015-08-17

若能得到一個和為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;
}