hdu4339 Query(multiset 或 线段树)

Query

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 998    Accepted Submission(s): 300


Problem Description
You are given two strings s1[0..l1], s2[0..l2] and Q - number of queries.
Your task is to answer next queries:
  1) 1 a i c - you should set i-th character in a-th string to c;
  2) 2 i - you should output the greatest j such that for all k (i<=k and k<i+j) s1[k] equals s2[k].
 

 

Input
The first line contains T - number of test cases (T<=25).
Next T blocks contain each test.
The first line of test contains s1.
The second line of test contains s2.
The third line of test contains Q.
Next Q lines of test contain each query:
  1) 1 a i c (a is 1 or 2, 0<=i, i<length of a-th string, 'a'<=c, c<='z')
  2) 2 i (0<=i, i<l1, i<l2)
All characters in strings are from 'a'..'z' (lowercase latin letters).
Q <= 100000.
l1, l2 <= 1000000.
 

 

Output
For each test output "Case t:" in a single line, where t is number of test (numbered from 1 to T).
Then for each query "2 i" output in single line one integer j.
 

 

Sample Input
1
aaabba
aabbaa
7
2 0
2 1
2 2
2 3
1 1 2 b
2 0
2 3
 
 
Sample Output
Case 1:
2
1
0
1
4
1
 
Source
 
题意:第一行输入一个整数,表示案例数;然后输入两个字符串;再然后输入一个数,表示操作的次数;
两个操作:
1 a i c  更新:表示第 a(a=1或a=2)个字符串中下标为 i 的字符用 c 替换;
2 i       访问:表示两个字符串从下标为 i 开始有多个字符是一样的。
 
法一:把所以不能匹配的下标存储在 multiset
View Code
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<set>
 5 #define MAXN 1000010
 6 
 7 using namespace std;
 8 
 9 char s[2][MAXN];
10 
11 int main()
12 {
13     int test,n,i,j,len1,len2,p,q,k=1;
14     char c[2];
15     multiset<int>ms;
16     multiset<int>::iterator it;
17     scanf("%d",&test);
18     while(test--)
19     {
20         ms.clear();
21         scanf("%s",s[0]);
22         scanf("%s",s[1]);
23         len1=strlen(s[0]);
24         len2=strlen(s[1]);
25         i=0;
26         while(i<len1&&i<len2)
27         {
28             if(s[0][i]!=s[1][i]) ms.insert(i);
29             i++;
30         }
31         ms.insert(i);
32         printf("Case %d:\n",k++);
33         scanf("%d",&n);
34         for(i=0;i<n;i++)
35         {
36             scanf("%d",&p);
37             if(p==2)
38             {
39                 scanf("%d",&j);
40                 it=ms.lower_bound(j);
41                 printf("%d\n",*it-j);
42             }
43             else
44             {
45                 scanf("%d %d %s",&q,&j,c);
46                 q--;
47                 if(s[0][j]!=s[1][j]) ms.erase(j);
48                 s[q][j]=*c;
49                 if(s[q^1][j]!=s[q][j]) ms.insert(j);
50             }
51         }
52     }
53     return 0;
54 }

 

法二:线段树中存储这区间第一个不能匹配的下标,转换成单点更新,区间最值

View Code
  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #define MAXN 1000000
  5 
  6 struct segtree
  7 {
  8     int left,right,acount;
  9 }tree[MAXN<<2];
 10 char s[2][MAXN];
 11 int INF;
 12 
 13 int min(int A,int B){return A<B?A:B;}
 14 
 15 int max(int A,int B){return A>B?A:B;}
 16 
 17 void build(int r,int a,int b)
 18 {
 19     tree[r].left=a;tree[r].right=b;
 20     tree[r].acount=INF;
 21     if(a<b)
 22     {
 23         int m=(a+b)>>1;
 24         build(r<<1,a,m);
 25         build(r<<1|1,m+1,b);
 26     }
 27 }
 28 
 29 void update(int r,int i,int key)
 30 {
 31     if(tree[r].left==tree[r].right)
 32     {
 33         tree[r].acount=key;
 34         return ;
 35     }
 36     int m=(tree[r].left+tree[r].right)>>1;
 37     if(i<=m) 
 38         update(r<<1,i,key);
 39     else 
 40         update(r<<1|1,i,key);
 41     tree[r].acount=min(tree[r<<1].acount,tree[r<<1|1].acount);
 42 }
 43 
 44 int find_min(int r,int a,int b)
 45 {
 46     if(a<=tree[r].left&&tree[r].right<=b)
 47         return tree[r].acount;  
 48     int m=(tree[r].left+tree[r].right)>>1;
 49     if(b<=m) 
 50         return find_min(r<<1,a,b);//对自己很无语了居然写成find_min(r<<1,a,m);
 51     else if(a>m) 
 52         return find_min(r<<1|1,a,b);//这里也是
 53     else 
 54         return min(find_min(r<<1,a,m),find_min(r<<1|1,m+1,b));
 55 }
 56 
 57 int main()
 58 {
 59 
 60 #ifndef ONLINE_JUDGE
 61     freopen("in.txt","r",stdin);
 62     freopen("out.txt","w",stdout);
 63 #endif
 64 
 65     int test,i,j,k=1,n,p,q,len;
 66     char c[2];
 67     scanf("%d",&test);
 68     while(test--)
 69     {
 70         scanf("%s",s[0]);
 71         scanf("%s",s[1]);
 72         len=min(strlen(s[0]),strlen(s[1]));
 73         INF=len+1;
 74         build(1,1,len);
 75         for(i=0;i<len;i++)
 76         {
 77             if(s[0][i]!=s[1][i]) update(1,i+1,i+1);
 78             else update(1,i+1,INF);
 79         }
 80         printf("Case %d:\n",k++);
 81         scanf("%d",&n);
 82         for(i=0;i<n;i++)
 83         {
 84             scanf("%d",&p);
 85             if(p==2)
 86             {
 87                 scanf("%d",&j);
 88                 if(j>=len)
 89                     printf("0\n");
 90                 else
 91                     printf("%d\n",find_min(1,j+1,len)-j-1);
 92             }
 93             else if(p==1)
 94             {
 95                 scanf("%d %d %s",&q,&j,c);
 96                 if(j>=len) continue;
 97                 q--;
 98                 if(s[q][j]==s[q^1][j]&&s[q^1][j]!=*c) update(1,j+1,j+1);
 99                 if(s[q][j]!=s[q^1][j]&&s[q^1][j]==*c) update(1,j+1,INF);
100                 s[q][j]=*c;
101             }
102         }
103     }
104     return 0;
105 }

 

 

posted @ 2012-08-04 07:55  mtry  阅读(492)  评论(1)    收藏  举报