hdu4339--Query(二分+树状数组)
题目大意:
给定两个字符串,有两种操作
1: 把第a(a==1 || a==2)个串第i个位置得字符改为c(输入的字符)
2: 求从第i个字符起接下来连续相同字符的个数
解题方法:
对于两个字符串,对应第i个位置得字符相同标1,不同标0,分别加入数组数组中
查询的话从第i个位置起到两个串最大长度的位置,通过二分查询结果。如果连续相同的话,区间和将等于区间的长度。
树状数组代码:
View Code
1 //Accepted 4339 3218MS 10008K 1651 B G++ 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX 1000001 5 6 char s1[MAX],s2[MAX]; 7 int c[MAX],tt[MAX]; 8 inline int lowbit(int a) { return a & (-a); } 9 inline int maxx(int a,int b) { return a > b ? a : b; } 10 void insert(int x,int d) 11 { 12 while(x < MAX) 13 { 14 c[x] += d; 15 x += lowbit(x); 16 } 17 } 18 19 int getsum(int x) 20 { 21 int sum = 0; 22 while(x > 0) 23 { 24 sum += c[x]; 25 x -= lowbit(x); 26 } 27 return sum; 28 } 29 30 void query(int l,int r) 31 { 32 int num = l - 1; 33 while(l <= r) 34 { 35 int mid = (l + r) >> 1; 36 int k = getsum(mid) - getsum(num); 37 if(k == mid - num) 38 l = mid + 1; 39 else 40 r = mid - 1; 41 } 42 printf("%d\n",r-num); 43 } 44 45 int main(void) 46 { 47 int i,j,t; 48 scanf("%d",&t); 49 for(i = 1; i <= t ; i++) 50 { 51 memset(c,0,sizeof(c)); 52 memset(tt,0,sizeof(tt)); 53 scanf("%s",s1); 54 scanf("%s",s2); 55 int len1,len2,len; 56 len1 = strlen(s1); 57 len2 = strlen(s2); 58 len = maxx(len1,len2); 59 for(j=0;j<len;j++) 60 { 61 if(s1[j]==s2[j]) 62 { 63 tt[j+1] = 1; 64 insert(j+1,1); 65 } 66 } 67 int q; 68 printf("Case %d:\n",i); 69 scanf("%d",&q); 70 while(q--) 71 { 72 int id,a; 73 scanf("%d",&id); 74 if(id == 1) 75 { 76 int x; 77 char ch; 78 scanf("%d %d %c",&a,&x,&ch); 79 if(a == 1) 80 { 81 s1[x] = ch; 82 } 83 else 84 { 85 s2[x] = ch; 86 } 87 if(s1[x] == s2[x]) 88 { 89 if(tt[x+1] == 0) 90 { 91 insert(x+1,1); 92 tt[x+1] = 1; 93 } 94 } 95 else 96 { 97 if(tt[x+1] == 1) 98 { 99 insert(x+1,-1); 100 tt[x+1] = 0; 101 } 102 } 103 } 104 else 105 { 106 scanf("%d",&a); 107 query(a+1,len); 108 } 109 } 110 } 111 return 0; 112 }
同样的方法用线段树求和就超时了,树状数组求和的效率还是比较高的
线段树代码:
View Code
1 //tle 2 #include <cstdio> 3 #include <cstring> 4 5 #define lson l , m , rt << 1 6 #define rson m + 1 , r , rt << 1 | 1 7 #define maxn 1000005 8 int sum[maxn<<2]; 9 char s1[maxn],s2[maxn]; 10 int tt[maxn]; 11 inline int maxx(int a,int b) { return a > b ? a : b; } 12 void PushUP(int rt) { 13 sum[rt] = sum[rt<<1] + sum[rt<<1|1]; 14 } 15 void build(int l,int r,int rt) { 16 if (l == r) { 17 sum[rt] = tt[l]; 18 return ; 19 } 20 int m = (l + r) >> 1; 21 build(lson); 22 build(rson); 23 PushUP(rt); 24 } 25 void update(int p,int add,int l,int r,int rt) { 26 if (l == r) 27 { 28 sum[rt] += add; 29 return ; 30 } 31 int m = (l + r) >> 1; 32 if (p <= m) update(p , add , lson); 33 else update(p , add , rson); 34 PushUP(rt); 35 } 36 int getsum(int L,int R,int l,int r,int rt) { 37 if (L <= l && r <= R) { 38 return sum[rt]; 39 } 40 int m = (l + r) >> 1; 41 int ret = 0; 42 if (L <= m) ret += getsum(L , R , lson); 43 if (R > m) ret += getsum(L , R , rson); 44 return ret; 45 } 46 void query(int l,int r) 47 { 48 int num = l - 1; 49 int len = r; 50 while(l <= r) 51 { 52 int mid = (l + r) >> 1; 53 int k = getsum(num+1,mid,1,len,1); 54 if(k == mid - num) 55 l = mid + 1; 56 else 57 r = mid - 1; 58 } 59 printf("%d\n",r-num); 60 } 61 62 int main(void) 63 { 64 int i,j,t; 65 scanf("%d",&t); 66 for(i = 1; i <= t ; i++) 67 { 68 memset(sum,0,sizeof(sum)); 69 memset(tt,0,sizeof(tt)); 70 scanf("%s",s1); 71 scanf("%s",s2); 72 int len1,len2,len; 73 len1 = strlen(s1); 74 len2 = strlen(s2); 75 len = maxx(len1,len2); 76 for(j=0;j<len;j++) 77 { 78 if(s1[j]==s2[j]) 79 { 80 tt[j+1] = 1; 81 update(j+1,1,1,len,1); 82 } 83 } 84 int q; 85 printf("Case %d:\n",i); 86 scanf("%d",&q); 87 while(q--) 88 { 89 int id,a; 90 scanf("%d",&id); 91 if(id == 1) 92 { 93 int x; 94 char ch; 95 scanf("%d %d %c",&a,&x,&ch); 96 if(a == 1) 97 { 98 s1[x] = ch; 99 } 100 else 101 { 102 s2[x] = ch; 103 } 104 if(s1[x] == s2[x]) 105 { 106 if(tt[x+1] == 0) 107 { 108 update(x+1,1,1,len,1); 109 tt[x+1] = 1; 110 } 111 } 112 else 113 { 114 if(tt[x+1] == 1) 115 { 116 update(x+1,-1,1,len,1); 117 tt[x+1] = 0; 118 } 119 } 120 } 121 else 122 { 123 scanf("%d",&a); 124 query(a+1,len); 125 } 126 } 127 } 128 return 0; 129 }