hdu 4339 Query
http://acm.hdu.edu.cn/showproblem.php?pid=4339
题意:给两串字符串,有两个操作:
1) 1 a i c - 将第a串的第i个字符修改成c;
2) 2 i - 求两个串从第i位置开始的最长相同长度。
思路:因为答案只和当前位置前面的有关,所以可以用树状数组。具体如下:
如果第i个位置上相同,则为0,不同则为1,这样就可以转化成求第i个位置后面一第一个1的位置。
这样用求第k大解之。(加上读入优化rank1)

#include<stdio.h> #include<string.h> #include<iostream> #define lowbit(x) (x)&(-x) using namespace std; const int maxn = 1000005; char as[2][maxn]; int n,sum[1<<21]; void add(int x,int v){for(;x<=n;x+=lowbit(x))sum[x]+=v;} int getsum(int x){int v=0;for(;x;x-=lowbit(x))v+=sum[x];return v;} int findk(int k) { int pos = 0,cnt = 0; for(int i = 20; i >= 0; -- i){ pos += (1<<i); if(pos>=n || cnt+sum[pos]>=k) pos -= (1<<i); else cnt += sum[pos]; }return pos + 1; } int scan(){ int res=0,ch; while(!((ch=getchar())>='0' && ch<='9')) if(ch==EOF) return 1<<30; res=ch-'0'; while((ch=getchar())>='0' && ch<='9') res=res*10+(ch-'0'); return res; } void readin() { int k; scanf("%s%s",as[0],as[1]); n = strlen(as[0]); k = strlen(as[1]); if(k > n) n = k; } void processing() { int i,j,k,t,a,b; char s[12]; n++; for(i = 0; i < n - 1; ++ i) if(as[0][i]^as[1][i]) add(i+1,1); sum[n] = 1; scanf("%d",&t); while(t--){ a = scan(); b = scan(); if(a==2){ k = getsum(b); j = findk(k+1); printf("%d\n",j - b - 1); }else{ --b; i = scan(); gets(s); if(as[b][i]==as[b^1][i]){ as[b][i] = s[0]; if(s[0]^as[b^1][i]) add(i+1,1); }else{ as[b][i] = s[0]; if(as[b][i]==as[b^1][i]) add(i+1,-1); } } } for(i = 0; i <= n; ++ i){ as[0][i] = as[1][i] = 0; sum[i] = 0; } } int main() { int T,cas=0; for(scanf("%d",&T);T--;){ readin(); printf("Case %d:\n",++cas); processing(); } return 0; }