1 aaabba aabbaa 7 2 0 2 1 2 2 2 3 1 1 2 b 2 0 2 3
Case 1: 2 1 0 1 4 1
题目分析:给2个字符串,2个操作,第一个操作就将某个字符串某个位置的字符换掉。第二个操作是查询2个字符串中某个位置开始向右最长连续相等的长度。
题目分析:线段树。比赛的时候竟然没做出来,还是太水了啊。。。
每个区间维护2个值:lc、rc分别表示当前区间左右两边连续相等的最长长度。查询的时候,假设查询p位置,那么只需要讨论p的位置即可。
对于一个区间,p的位置只有3种可能:
如图,当p在p1位置的时候,直接返回a1,当p在p3位置的时候,显然a2是答案的一部分,但是有可能右边还有解,所以还要再查询当前区间右端点的右边一个点,当p在p2位置的时候,p的位置还是不确定的,所以继续向下查询,缩小p的范围,直到能确定p的位置为止。
详情请见代码:
#include <iostream> #include<cstdio> #include<cstring> using namespace std; const int N = 1000005; char s1[N],s2[N]; struct node { int lc,rc;//当前区间左右连续相等 }tree[N<<2]; int l1,l2; int n,m; int Min(int a,int b) { return a < b?a:b; } void pushup(int num,int s,int e) { int ls = num<<1; int rs = num<<1|1; int mid = (s + e)>>1; tree[num].lc = tree[ls].lc; if(tree[ls].lc == mid - s + 1) tree[num].lc += tree[rs].lc; tree[num].rc = tree[rs].rc; if(tree[rs].rc == e - mid) tree[num].rc += tree[ls].rc; } void build(int num,int s,int e) { tree[num].lc = tree[num].rc = 0; if(s == e) { if(s1[s - 1] == s2[s - 1]) { tree[num].lc = tree[num].rc = 1; } return; } int mid = (s + e)>>1; build(num<<1,s,mid); build(num<<1|1,mid + 1,e); pushup(num,s,e); } void update(int num,int s,int e,int pos) { if(pos > e) return; if(s == e) { if(s1[s - 1] == s2[s - 1]) { tree[num].lc = tree[num].rc = 1; } else tree[num].lc = tree[num].rc = 0; return; } int mid = (s + e)>>1; if(pos <= mid) update(num<<1,s,mid,pos); else update(num<<1|1,mid + 1,e,pos); pushup(num,s,e); } int query(int num,int s,int e,int pos) { if(pos > e) return 0; if(s1[pos - 1] != s2[pos - 1]) return 0; if(pos - s + 1 <= tree[num].lc) { return tree[num].lc - pos + s; } if(e - pos + 1 <= tree[num].rc) { return e - pos + 1 + query(1,1,n,e + 1); } int mid = (s + e)>>1; if(pos <= mid) return query(num<<1,s,mid,pos); else return query(num<<1|1,mid + 1,e,pos); } int main() { int t; int op,a,b; char ch[3]; scanf("%d",&t); int cas = 0; while(t --) { scanf("%s",s1); scanf("%s",s2); l1 = strlen(s1); l2 = strlen(s2); n = Min(l1,l2); build(1,1,n); scanf("%d",&m); printf("Case %d:\n",++cas); while(m --) { scanf("%d",&op); if(op == 2) { scanf("%d",&a); printf("%d\n",query(1,1,n,a + 1)); } else { scanf("%d%d%s",&a,&b,ch); if(a == 1) s1[b] = ch[0]; else s2[b] = ch[0]; update(1,1,n,b + 1); } } } return 0; } //1843MS 18624K
特别感谢@男神帮忙找到了一直ole的bug。。。
最近好不顺啊啊。。。