[BalkanOI2018]Election
Solution
推式子题,然后转换。考场上没有耐心,实际上应该能想出来。
答案是将 (C) 看成 (1),(T) 看成 (-1) 后,区间和减去区间最大子段和。
#include<stdio.h>
#define N 500007
#define rint register int
#define lid id<<1
#define rid id<<1|1
inline int read(){
int x=0,flag=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')flag=0;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
return flag? x:-x;
}
inline void out(int x){
if(x<0) putchar('-'),x=-x;
if(9<x) out(x/10);
putchar(x%10^'0');
}
struct Node{
int lm,rm,m,sum;
void init(int x){lm=rm=m=sum=x;}
}t[N<<2];
int a[N];
inline int max(int x,int y){return x>y? x:y;}
inline void merge(Node &id,Node x,Node y){
id.lm=max(x.lm,x.sum+y.lm);
id.rm=max(y.rm,y.sum+x.rm);
id.sum=x.sum+y.sum;
id.m=max(x.rm+y.lm,max(id.lm,id.rm));
id.m=max(id.m,max(x.m,y.m));
}
inline void build(int id,int lf,int rf){
if(lf==rf) t[id].init(a[lf]);
else{
int mid=(lf+rf)>>1;
build(lid,lf,mid);
build(rid,mid+1,rf);
merge(t[id],t[lid],t[rid]);
}
}
int l,r;
inline Node query(int id,int lf,int rf){
if(l<=lf&&rf<=r) return t[id];
else{
int mid=(lf+rf)>>1;
if(r<=mid) return query(lid,lf,mid);
if(l>mid) return query(rid,mid+1,rf);
Node ret;ret.init(0);
merge(ret,query(lid,lf,mid),query(rid,mid+1,rf));
return ret;
}
}
int n,m;
char s[N];
int main(){
// freopen("elections.in","r",stdin);
// freopen("elections.out","w",stdout);
n=read();
scanf("%s",s+1);
for(rint i=1;i<=n;i++)
a[i]=(s[i]=='C'? 1:-1);
build(1,1,n);
for(rint i=1;i<=n;i++)
a[i]+=a[i-1];
m=read();
for(rint i=1;i<=m;i++){
l=read(),r=read();
Node ans=query(1,1,n);
out(max(0,ans.m)-(a[r]-a[l-1]));
putchar('
');
}
}