2012年的多校题
看了一眼一位会是字符串类的题,没有细想
仔细看要维护的就是每个位置想不想等,也就是一串 01 01 01序列
用线段树维护区间和
二分求解即可
#include <bits/stdc++.h>
using namespace std;
#define ls (p<<1)
#define rs (p<<1|1)
#define MID ((l+r)>>1)
#define lson ls,l,MID
#define rson rs,MID+1,r
const int maxn=4e6+10;
char s[3][maxn];
int sam[maxn],a[maxn],len;
void build(int p,int l,int r)
{
if( l==r ) { a[p]=sam[l]; return; }
build(lson); build(rson);
a[p] = a[ls]+a[rs];
}
void update(int p,int l,int r,int id,int val)
{
if( l>id||r<id ) return;
if( l==r&&l==id ) { a[p]=val; return; }
update(lson,id,val); update(rson,id,val);
a[p] = a[ls]+a[rs];
}
int query(int p,int l,int r,int L,int R)
{
if( r<L||l>R ) return 0;
if( l>=L&&r<=R ) return a[p];
return query(lson,L,R)+query(rson,L,R);
}
bool isok(int l,int r)
{
if( r-l+1==query(1,1,len,l,r) ) return true;
return false;
}
int main()
{
int t,q,casenum=0;
cin >> t;
while( t-- )
{
scanf("%s%s",s[1],s[2] );
int len1=strlen(s[1]), len2=strlen(s[2]);
len=min( len1,len2 );
for( int i=0;i<len;i++ )
sam[i] = ( s[1][i]==s[2][i] );
build( 1,0,len-1 );
scanf("%d",&q);
printf("Case %d:\n",++casenum);
while( q-- )
{
int type,id,pos; char c;
scanf("%d",&type);
if( type==1 )
{
cin >> id >> pos >> c;
if( pos>=len ) continue;
s[id][pos]=c;
if( s[id][pos]==s[3-id][pos] ) sam[pos]=1;
else sam[pos]=0;
update(1,0,len-1,pos,sam[pos] );
}
else
{
scanf("%d",&pos);
if( pos>=len )
{
printf("0\n");
continue;
}
int l=pos,r=len-1,mid,ans=0;
while( r>=l )
{
mid = l+r>>1;
int ok = query(1,0,len-1,pos,mid);
if( ok==mid-pos+1 ) l=mid+1,ans=mid-pos+1;
else r=mid-1;
}
printf("%d\n",ans);
}
}
}
}