题意是给你两个字符串 进行两种操作 1: 修改其中一个字符串里的某个字符2: 询问从i起两个字符串最多由多少个是相同的;
先说一下做之前的想法 ,我是看别人介绍树状数组是看到这道题的 本也想用树状数组做 ,没想上去 然后就改为线段树了 ,有很明显的点更新,区间查询,所以选择线段树;
思路: 每个节点num【】 存3个值 p1 p2 flash flash表示当前节点两个字符串是不是一样的 若是则为1否则为0 p1 p2为当前两个字符串的字符(其实只有在最底端的节点 p1 p2才有意义) 题目给的是字符区间 而真正修改的是点 所以得先处理字符串加到线段树里也就是deal函数 (偷懒写在一个函数里果断超时了!!!) 然后对点来更新
对于查询 我是用的二分 开始j=最大长度 然后二分到底 虽然时间可能长点 但代码比较简单
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; #define LL(x) (x<<1) #define RR(x) ((x<<1)|1) char str1[1000010],str2[1000010]; struct node { char p1,p2; int flash; }num[4*1000000]; int max(int a,int b) { return a>b?a:b; } int deal(int L,int R,int left,int right,int mark,int k,char str[]) { if(L==left&&right==R&&L==R) { if(k==1) num[mark].p1=str[L-1]; else num[mark].p2=str[L-1]; if(num[mark].p1==num[mark].p2) num[mark].flash=1; else num[mark].flash=0; return 0; } int mid=(L+R)/2; if(right<=mid) { deal(L,mid,left,right,LL(mark),k,str); } else if(left>mid) { deal(mid+1,R,left,right,RR(mark),k,str); } else { deal(L,mid,left,mid,LL(mark),k,str); deal(mid+1,R,mid+1,right,RR(mark),k,str); } if(num[LL(mark)].flash==0||num[RR(mark)].flash==0) num[mark].flash=0; else num[mark].flash=1; return 0; } int update(int L,int R,int dis,int mark,int k,char p) { if(L==R&&L==dis) { if(k==1) num[mark].p1=p; else num[mark].p2=p; if(num[mark].p1==num[mark].p2) num[mark].flash=1; else num[mark].flash=0; return 0; } if(num[mark].flash==1) { num[LL(mark)].flash=num[RR(mark)].flash=num[mark].flash; } int mid=(L+R)/2; if(dis<=mid) { update(L,mid,dis,LL(mark),k,p); } else update(mid+1,R,dis,RR(mark),k,p); if(num[LL(mark)].flash==0||num[RR(mark)].flash==0) { num[mark].flash=0; } else num[mark].flash=1; return 0; } int find(int L,int R ,int left,int right,int mark) { if(num[mark].flash==1) return 1; if(left==L&&right==R) return -1; int mid=(L+R)/2; if(right<=mid) { return find(L,mid,left,right,LL(mark)); } else if(left>mid) { return find(mid+1,R,left,right,RR(mark)); } else { int t1=find(L,mid,left,mid,LL(mark)); int t2=find(mid+1,R,mid+1,right,RR(mark)); if(t1==-1||t2==-1) return -1; else return 1; } } int main() { int len1,len2,T,i,d=1; scanf("%d",&T); while(T--) { printf("Case %d:\n",d++); scanf("%s%s",str1,str2); len1=strlen(str1); len2=strlen(str2); int L=1,R=max(len1,len2); memset(num,0,sizeof(num)); deal(L,R,1,len1,1,1,str1); deal(L,R,1,len2,1,2,str2); int Q; scanf("%d",&Q); while(Q--) { int dis,x,k; char str[5]; scanf("%d",&x); if(x==1) { scanf("%d%d%s",&k,&dis,str); dis++; update(L,R,dis,1,k,str[0]); } else { int left; scanf("%d",&left); int t=left; left++; int right=R; while(left<=right) { int mid=(left+right)/2; if(find(L,R,left,mid,1)==-1) right=mid-1; else left=mid+1; } printf("%d\n",left-t-1); } } } return 0; }
时间: 2024-10-03 05:42:22