http://acm.hdu.edu.cn/showproblem.php?pid=4339
这次多校我就出了这么个水题,伤心呀……
思路: 单点更新,线段树每个节点记录该区间从左向右第一个不一样的点的位置,这道题目的难点就是在于区间的合并的时候
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=1000100;
int d[maxn*4];
char s1[maxn],s2[maxn];
void build(int l,int r,int rt)
{
if(l==r)
{
if(s1[l]==s2[r]) d[rt]=l;
else d[rt]=-1;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
if(d[rt<<1]==m) d[rt]=max(d[rt<<1],d[rt<<1|1]);
else d[rt]=d[rt<<1];
}
void update(int id,int p,char cc,int l,int r,int rt)
{
if(l==r)
{
if(id==1) s1[p]=cc;
else s2[p]=cc;
if(s1[l]==s2[r]) d[rt]=l;
else d[rt]=-1;
return;
}
int m=(l+r)>>1;
if(p<=m) update(id,p,cc,lson);
else update(id,p,cc,rson);
if(d[rt<<1]==m) d[rt]=max(d[rt<<1],d[rt<<1|1]);
else d[rt]=d[rt<<1];
//cout<<rt<<" "<<l<<" "<<r<<" "<<d[rt]<<endl;
}
int query(int L,int R,int l,int r,int rt)
{
if(L==l&&R==r) return d[rt];
int m=(l+r)>>1,ret1=-1,ret2=-1;
if(R<=m) return query(L,R,lson);
if(L>m) return query(L,R,rson);
ret1=query(L,m,lson);
if(ret1==m) ret2=query(m+1,r,rson);
if(ret1==m) return max(ret1,ret2);
else return ret1;
}
int main()
{
int ca,Q,id,p,Max,cas=1;
char cc[4];
scanf("%d",&ca);
while(ca--)
{
scanf("%s %s",s1,s2);
scanf("%d",&Q);
int len1=strlen(s1),len2=strlen(s2);
Max=min(len1,len2)-1;
build(0,Max,1);
printf("Case %d:\n",cas++);
while(Q--)
{
scanf("%d",&id);
if(id==1)
{
scanf("%d %d %s",&id,&p,cc);
update(id,p,cc[0],0,Max,1);
}
else
{
scanf("%d",&p);
int ans=query(p,Max,0,Max,1);
if(ans==-1) printf("0\n");
else printf("%d\n",ans-p+1);
}
}
}
return 0;
}