[关闭]
@xingxing 2017-03-31T15:40:00.000000Z 字数 1923 阅读 1132

专题二 线段树

线段树


[题目][A]

敌兵布阵

题目大意:

有T组数据。
第一行为N(N <= 50000)个营地,接下来一行有N个正整数ai(第i个营地里初始为ai)(1 <= ai <= 50),接下来每一行有一条命令。
Add i j(j <= 30)
Sub i j(j <= 30)
Query i j (i <= j)
End 结束
每组数据最多有40000条命令。
每组数据,要求输出“Case i:”和回车,对于每个Query命令,输出一个整数(询问段中的总人数,题目保证在int以内)占一行。

解题思路:

利用线段树,定义一个结构体,保存节点的l,r,value。然后建立一棵有N个节点的树。对于Add和Sub命令,即从下往上,更新每个节点的value。对于Query命令,即分区间讨论该区间和当前节点的范围关系,然后适当的把要求的范围进行划分。

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. using namespace std;
  6. const int maxn = 3*50000;//?1
  7. typedef struct model
  8. {
  9. int l,r;
  10. int value;
  11. }segNODE;
  12. segNODE segTree[maxn];
  13. char order[10];
  14. int num[50005];
  15. int build(int rt,int l,int r)
  16. {
  17. segTree[rt].l = l;
  18. segTree[rt].r = r;
  19. segTree[rt].value = 0;
  20. if(l == r)
  21. {
  22. segTree[rt].value = num[l];
  23. return segTree[rt].value;
  24. }
  25. else
  26. {
  27. return segTree[rt].value = build(rt*2,l,(l+r)/2) + build(rt*2+1,(l+r)/2+1,r);
  28. }
  29. }
  30. int query(int node,int s,int e,int left,int right)
  31. {
  32. int mid;
  33. if(left == s && right == e) return segTree[node].value;
  34. //if(left == right) return
  35. mid = (s+e)/2;
  36. if(mid >= left && right > mid)
  37. {
  38. return query(node*2,segTree[node*2].l,segTree[node*2].r,left,mid) + query(node*2+1,segTree[node*2+1].l,segTree[node*2+1].r,mid+1,right);
  39. }
  40. else
  41. {
  42. if(right <= mid)
  43. return query(node*2,segTree[node*2].l,segTree[node*2].r,left,right);
  44. else return query(node*2+1,segTree[node*2+1].l,segTree[node*2+1].r,left,right);
  45. }
  46. }
  47. void solve(int no,int sum,int node)
  48. {
  49. segTree[node].value += sum;
  50. if(segTree[node].l != segTree[node].r)
  51. {
  52. if(no <= (segTree[node].l+segTree[node].r)/2) solve(no,sum,node*2);
  53. else solve(no,sum,node*2+1);
  54. }
  55. }
  56. int main()
  57. {
  58. //freopen("in.txt","r",stdin);
  59. int t,k = 0;
  60. int n;
  61. int i;
  62. int s,e;
  63. scanf("%d",&t);
  64. while(t--)
  65. {
  66. k++;
  67. printf("Case %d:\n",k);
  68. scanf("%d",&n);
  69. for(i = 1;i <= n;i++)
  70. {
  71. scanf("%d",&num[i]);
  72. }
  73. build(1,1,n);
  74. while(1)
  75. {
  76. // getchar();
  77. scanf("%s",order);
  78. //puts(order);
  79. //system("pause");
  80. if(strcmp(order,"End") == 0) break;
  81. scanf("%d%d",&s,&e);
  82. if(strcmp(order,"Query") == 0)
  83. {
  84. //printf("qqqqqq\n");
  85. printf("%d\n",query(1,1,n,s,e));
  86. }
  87. if(strcmp(order,"Add") == 0)
  88. {
  89. //printf("aaaaaa\n");
  90. solve(s,e,1);
  91. }
  92. if(strcmp(order,"Sub") == 0)
  93. {
  94. solve(s,-e,1);
  95. }
  96. }
  97. }
  98. return 0;
  99. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注