[关闭]
@Acqua 2018-12-14T11:08:16.000000Z 字数 1153 阅读 986

HDU4339 Query(Dec. 11th, 2018)

树状数组

题目描述
题意:给定两个字符串个操作,分别是:
1. 输入,把的第个字符改为
2. 输入,求两个字符串从第位开始最长公共子串。

思路(来自题解):
1. 用树状数组维护字符串,不同为1,同为0。
2. 二分查找坐标最大的能够使

代码:

  1. // La Lune
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. #define wt(x) (x & -x)
  7. #define rev(x) (x == 1 ? 2 : 1)
  8. using namespace std;
  9. const int N = 1e6 + 5;
  10. int n, c[N]; char s[3][N];
  11. inline void add(int pos, int x) {for(int i = pos; i <= n; i += wt(i)) c[i] += x;}
  12. inline int que(int pos) {int res = 0; for(int i = pos; i >= 1; i -= wt(i)) res += c[i]; return res;}
  13. int main(){
  14. int T, cnt = 0; scanf("%d", &T);
  15. while(T--){
  16. memset(c, 0, sizeof(c));
  17. scanf("%s\n%s", s[1] + 1, s[2] + 1);
  18. n = max(strlen(s[1] + 1), strlen(s[2] + 1));
  19. for(int i = 1; i <= n; i++) if(s[1][i] != s[2][i]) add(i, 1);
  20. printf("Case %d:\n", ++cnt);
  21. int q; scanf("%d", &q);
  22. for(int i = 1; i <= q; i++){
  23. int ctrl, pos;
  24. scanf("%d", &ctrl);
  25. if(ctrl == 1){
  26. int str; char mv;
  27. scanf("%d %d %c\n", &str, &pos, &mv); pos++;
  28. if(s[str][pos] == mv) continue;
  29. else if(s[str][pos] == s[rev(str)][pos]) add(pos, 1);
  30. else if(s[rev(str)][pos] == mv) add(pos, -1);
  31. s[str][pos] = mv;
  32. }
  33. else{
  34. scanf("%d", &pos); pos++;
  35. int l = pos - 1, r = n, ans = 0, ref = que(pos - 1);
  36. while(l <= r){
  37. int mid = l + r >> 1;
  38. if(que(mid) - ref == 0) ans = mid, l = mid + 1;
  39. else r = mid - 1;
  40. }
  41. printf("%d\n", ans - pos + 1);
  42. }
  43. }
  44. }
  45. return 0;
  46. }


反思

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注