当前位置:   article > 正文

UVA 12663 (线段树区间更新+二分查找,Q次区间更新后,求满足结果大于K的个数)_线段树 区间大于k的个数

线段树 区间大于k的个数


看见这种区间更新的题目,首先想到的就是线段树的区间更新。本体套用线段树的区间更新模板,更新的区间要二分去找。

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. #define MAX 200009
  5. #define LL long long int
  6. using namespace std;
  7. LL a[MAX],cnt;
  8. struct Node {
  9. LL L;
  10. LL R;
  11. Node *pL;
  12. Node *pR;
  13. LL sum;
  14. LL add;
  15. } tree[4*MAX];
  16. LL n,m,k;
  17. LL ans;
  18. LL mid(struct Node *root) {
  19. return (root->L+root->R)/2;
  20. }
  21. LL Search(LL low,LL high,LL goal) {
  22. LL mid;
  23. while(low<=high){
  24. mid=(low+high)/2;
  25. if(goal<=a[mid]){
  26. high=mid-1;
  27. }else{
  28. low=mid+1;
  29. }
  30. }
  31. return low;
  32. }
  33. void build(struct Node *root,LL L,LL R) {
  34. root->L=L;
  35. root->R=R;
  36. root->add=0;
  37. if(L==R) return;
  38. LL midd=(L+R)/2;
  39. cnt++;
  40. root->pL=tree+cnt;
  41. build(root->pL,L,midd);
  42. cnt++;
  43. root->pR=tree+cnt;
  44. build(root->pR,midd+1,R);
  45. }
  46. void add(struct Node *root, LL L, LL R, LL val) {
  47. if(root->L==L&&root->R==R) {
  48. root->add+=val;
  49. return;
  50. }
  51. LL midd=mid(root);
  52. if(R<=midd)add(root->pL, L, R, val);
  53. else if(L>midd) add(root->pR, L, R, val);
  54. else {
  55. add(root->pL, L, mid(root), val);
  56. add(root->pR, mid(root)+1, R,val);
  57. }
  58. }
  59. LL query(struct Node *root, LL L, LL R){
  60. if(L == R){
  61. if(root->add>=k) ans ++;
  62. return 0;
  63. }
  64. LL midd=mid(root);
  65. add(root->pL, root->L, midd, root->add);
  66. add(root->pR, midd+1, root->R, root->add);
  67. root->add=0;
  68. if(R<=midd) return query(root->pL, L, R);
  69. else if(L>midd) return query(root->pR, L, R);
  70. else return query(root->pL, L, midd)+query(root->pR, midd+1, R);
  71. }
  72. int main() {
  73. int t=1;
  74. while(~scanf("%lld %lld %lld",&n,&m,&k)) {
  75. cnt=0;
  76. ans=0;
  77. for(LL i=1; i<=n; i++) {
  78. scanf("%lld",&a[i]);
  79. }
  80. sort(a+1,a+n+1);
  81. build(tree,1,n);
  82. LL first=2,second;
  83. for(LL i=0; i<m; i++) {
  84. scanf("%lld",&second);
  85. LL firsttmp=lower_bound(a + 1, a + n + 1, first) - a;
  86. LL secondtmp = upper_bound(a + 1, a + n + 1, second) - a - 1;
  87. if(firsttmp>secondtmp) continue;
  88. // if(secondtmp>n) secondtmp=n;
  89. scanf("%lld",&first);
  90. if(secondtmp < firsttmp) continue;
  91. add(tree,firsttmp,secondtmp,1);
  92. first++;
  93. }
  94. query(tree,1,n);
  95. printf("Case %d: %lld\n",t++, ans);
  96. }
  97. return 0;
  98. }
  99. /*
  100. 10 10 2
  101. 2 4 6 9 6 2 4 3 19 39
  102. 5 2
  103. 6 3
  104. 9 2
  105. 8 3
  106. 4 3
  107. 9 6
  108. 8 2
  109. Case 1: 6
  110. 9 8 2
  111. 3 7 2 9 8 4 3 2 1
  112. 5 2
  113. 6 3
  114. 9 2
  115. 8 4
  116. 9 2
  117. 10 6
  118. 46 5
  119. 10 3
  120. Case 2: 6
  121. 4 2 2
  122. 2 2 2 2
  123. 5 2
  124. 7 2
  125. Case 3: 0
  126. */

还有一种方法,叫做差分,这适用于Q次更新,但是只有最后一次查询的状况,每次查询的时间复杂度是O(n).

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. using namespace std;
  5. #define MAX 100009
  6. #define inf 100000009
  7. int a[MAX],num[MAX],ans[MAX];
  8. int main(){
  9. int n,m,k,t=1;
  10. while(~scanf("%d %d %d",&n,&m,&k)){
  11. memset(num,0,sizeof(num));
  12. for(int i=1;i<=n;i++){
  13. scanf("%d",&a[i]);
  14. }
  15. sort(a+1,a+n+1);
  16. int first=2,second;
  17. for(int i=0;i<m;i++){
  18. scanf("%d",&second);
  19. int firsttmp=lower_bound(a+1,a+n+1,first)-a;
  20. int secondtmp=upper_bound(a+1,a+1+n,second)-a-1;
  21. num[firsttmp]++;
  22. num[secondtmp+1]--;
  23. scanf("%d",&first);
  24. first++;
  25. }
  26. int cnt=0;
  27. ans[0]=0;
  28. for(int i=1;i<=n;i++){
  29. ans[i]=ans[i-1]+num[i];
  30. if(ans[i]>=k) cnt++;
  31. }
  32. printf("Case %d: %d\n",t++, cnt);
  33. }
  34. return 0;
  35. }



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/180163
推荐阅读
相关标签
  

闽ICP备14008679号