E - Tunnel Warfare HDU - 1540

对这个题目的思考:首先我们已经意识到这个是一个线段树,要利用线段树来解决问题,但是怎么解决呢,这个摧毁和重建的操作都很简单,但是这个查询怎么查呢,

这个是不是要判断这一个点左边和右边最远的距离,然后相加起来就可以了,所以就是维护一个区间最左边和最右边的值,然后把他们合并就是最大值。

这个最左边的值 pre_max = 子左节点的 pre_max

如果这个 pre_max==len 那就可以合并子右节点的 pre_max

最右值同理

这个都知道了就只剩下细心一点写这个题目了。

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <queue>
  5. #include <vector>
  6. #include <algorithm>
  7. #include <string>
  8. #include <stack>
  9. #include <iostream>
  10. #include <map>
  11. #define inf 0x3f3f3f3f
  12. #define inf64 0x3f3f3f3f3f3f3f3f
  13. using namespace std;
  14. const int maxn = 1e5 + ;
  15. typedef long long ll;
  16. struct node
  17. {
  18. int l, r, len;
  19. int pre_max, last_max;
  20. }tree[maxn*];
  21.  
  22. void push_up(int id)
  23. {
  24. tree[id].pre_max = tree[id << ].pre_max;
  25. tree[id].last_max = tree[id << | ].last_max;
  26. if (tree[id << ].len == tree[id << ].pre_max) tree[id].pre_max += tree[id<<|].pre_max;
  27. if (tree[id << | ].len == tree[id << | ].last_max) tree[id].last_max += tree[id << ].last_max;
  28. // printf("tree[%d].max=%d tree[%d].min=%d\n", id, tree[id].pre_max, id, tree[id].last_max);
  29. // printf("tree[%d].max=%d tree[%d].min=%d\n", id << 1, tree[id << 1].pre_max, id << 1, tree[id << 1].last_max);
  30. // printf("tree[%d].max=%d tree[%d].min=%d\n", id << 1 | 1, tree[id << 1 | 1].pre_max, id << 1 | 1, tree[id << 1 | 1].last_max);
  31. }
  32.  
  33. void build(int id,int l,int r)
  34. {
  35. tree[id].l = l;
  36. tree[id].r = r;
  37. tree[id].len = r - l + ;
  38. if(l==r)
  39. {
  40. tree[id].last_max = tree[id].pre_max = ;
  41. return;
  42. }
  43. int mid = (l + r) >> ;
  44. build(id << , l, mid);
  45. build(id << | , mid + , r);
  46. push_up(id);
  47. }
  48.  
  49. void update(int id,int pos,int val)
  50. {
  51. //printf("id=%d pos=%d val=%d\n", id, pos, val);
  52. int l = tree[id].l;
  53. int r = tree[id].r;
  54. if(l==r)
  55. {
  56. tree[id].last_max = tree[id].pre_max = val;
  57. return;
  58. }
  59. int mid = (l + r) >> ;
  60. if (pos <= mid) update(id << , pos, val);
  61. else update(id << | , pos, val);
  62. push_up(id);
  63. }
  64.  
  65. int query_pre(int id,int x,int y)
  66. {
  67. int l = tree[id].l;
  68. int r = tree[id].r;
  69. //printf("id=%d l=%d r=%d x=%d y=%d\n", id, l, r, x, y);
  70. if(x<=l&&y>=r) return tree[id].pre_max;
  71. int mid = (l + r) >> ;
  72. int ans = , res = ;
  73. if (x <= mid) ans = query_pre(id << , x, y);
  74. if (y > mid) res = query_pre(id << | , x, y);
  75. // printf("id=%d res=%d ans=%d\n", id, res, ans);
  76. if (ans >= mid - x + ) return ans += res;//这个区间长度就是mid-x+1 因为mid 是在里面的所以要+1
  77. return ans;
  78. }
  79.  
  80. int query_last(int id, int x, int y) {
  81. int l = tree[id].l;
  82. int r = tree[id].r;
  83. //printf("id=%d l=%d r=%d x=%d y=%d \n", id, l, r, x, y);
  84. if (x <= l && y >= r) return tree[id].last_max;
  85. int mid = (l + r) >> ;
  86. int ans = , res = ;
  87. if (x <= mid) ans = query_last(id << , x, y);
  88. if (y > mid) res = query_last(id << | , x, y);
  89. //printf("Ans=%d res=%d\n", ans, res);
  90. if (res >= y - mid) res += ans;//区间长度为 y-mid mid不在里面
  91. return res;
  92. }
  93.  
  94. int main()
  95. {
  96. int m, n;
  97. while(scanf("%d%d", &n, &m)!=EOF)
  98. {
  99. stack<int>sta;
  100. build(, , n);
  101. while(m--)
  102. {
  103. char s[];
  104. int x;
  105. scanf("%s", s);
  106. if(s[]=='D')
  107. {
  108. scanf("%d", &x);
  109. sta.push(x);
  110. update(, x, );
  111. }
  112. else if(s[]=='R')
  113. {
  114. if(!sta.empty())
  115. {
  116. int num = sta.top(); sta.pop();
  117. update(, num, );
  118. }
  119. }
  120. else if(s[]=='Q')
  121. {
  122. scanf("%d", &x);
  123. int ans = query_pre(, x, n);
  124. ans += query_last(, , x);
  125. if(ans) printf("%d\n", ans - );
  126. else printf("0\n");
  127. }
  128. }
  129. }
  130. return ;
  131. }

线段树的区间合并

 
对这个题目的思考:这个题目不太会写,对于区间合的基本套路还是不太熟悉,这个题目看了题解之后(推荐题解 题解传送门)还是很清楚的。
我们知道这个是一个区间合并的线段树,和区间息息相关,这个要求长度为 w 的最左边的区间,还要求起点。
长度确定,所以我们就一个域是求最大长度的,因为要最左边的区间,而且我们要求最大长度就有合并操作,
所以我们要确定一个从左边开始最长的和从右边开始最长的,这个就和上面的差不多。
这个就是大致思路,剩下就是一些细节了。
一定要仔细点写,然后wa到哭

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <queue>
  5. #include <vector>
  6. #include <algorithm>
  7. #include <string>
  8. #include <stack>
  9. #include <iostream>
  10. #include <map>
  11. #define inf 0x3f3f3f3f
  12. #define inf64 0x3f3f3f3f3f3f3f3f
  13. using namespace std;
  14. const int maxn = 1e5 + ;
  15. typedef long long ll;
  16. struct node {
  17. int l, r, lazy, len;
  18. int pre_max, last_max, max;
  19. }tree[maxn * ];
  20.  
  21. void push_up(int id) {
  22. tree[id].pre_max = tree[id << ].pre_max;
  23. tree[id].last_max = tree[id << | ].last_max;
  24. if (tree[id << ].pre_max == tree[id << ].len) tree[id].pre_max += tree[id << | ].pre_max;
  25. if (tree[id << | ].last_max == tree[id << | ].len) tree[id].last_max += tree[id << ].last_max;
  26. tree[id].max = max(max(tree[id<<].max, tree[id<<|].max), tree[id << ].last_max + tree[id << | ].pre_max);
  27. //printf("tree[%d].pre_max=%d tree[%d].last_max=%d\n", id, tree[id].pre_max, id, tree[id].last_max);
  28. }
  29.  
  30. void build(int id, int l, int r) {
  31. tree[id].l = l;
  32. tree[id].r = r;
  33. tree[id].lazy = -;
  34. tree[id].len = tree[id].last_max = tree[id].pre_max = tree[id].max = r - l + ;
  35. //printf("tree[%d].pre_max=%d tree[%d].last_max=%d\n", id, tree[id].pre_max, id, tree[id].last_max);
  36. if (l == r) return;
  37. int mid = (l + r) >> ;
  38. build(id << , l, mid);
  39. build(id << | , mid + , r);
  40. }
  41.  
  42. void push_down(int id) {
  43. if (tree[id].lazy != -) {
  44. tree[id << ].lazy = tree[id << | ].lazy = tree[id].lazy;
  45.  
  46. if (tree[id].lazy) {
  47. tree[id << ].last_max = tree[id << ].pre_max = tree[id << ].max = tree[id << ].len;
  48. tree[id << | ].last_max = tree[id << | ].pre_max = tree[id << | ].max = tree[id << | ].len;
  49. }
  50. else {
  51. tree[id << ].last_max = tree[id << ].pre_max = tree[id << ].max = ;
  52. tree[id << | ].last_max = tree[id << | ].pre_max = tree[id << | ].max = ;
  53. }
  54. tree[id].lazy = -;
  55. }
  56. }
  57.  
  58. void update(int id, int x, int y, int val) {
  59. // printf("id=%d x=%d y=%d val=%d\n", id, x, y, val);
  60. int l = tree[id].l;
  61. int r = tree[id].r;
  62. if (x == l && y == r) {
  63. tree[id].lazy = val;
  64. if (val) tree[id].last_max = tree[id].pre_max = tree[id].max = tree[id].len;
  65. else tree[id].last_max = tree[id].pre_max = tree[id].max = ;
  66. return;
  67. }
  68. push_down(id);
  69. int mid = (l + r) >> ;
  70. if (y <= mid) update(id << , x, y, val);
  71. else if (mid + <= x) update(id << | , x, y, val);
  72. else {
  73. update(id << , x, mid, val);
  74. update(id << | , mid + , y, val);
  75. }
  76. push_up(id);
  77. }
  78.  
  79. int query(int id, int val) {
  80. int l = tree[id].l;
  81. int r = tree[id].r;
  82. //printf("id=%d l=%d r=%d\n", id, l, r);
  83. if (l == r) return l;
  84. int mid = (l + r) >> ;
  85. push_down(id);
  86. if (tree[id << ].max >= val) return query(id << , val);
  87. //printf("id1=%d\n", id);
  88. if (tree[id << ].last_max + tree[id << | ].pre_max >= val) return mid - tree[id << ].last_max + ;
  89. //printf("tree[%d].last=%d tree[%d].pre=%d id2=%d\n", id<<1,tree[id<<1].last_max,id<<1|1,tree[id<<1|1].pre_max,id);
  90. return query(id << | , val);
  91. }
  92.  
  93. int main() {
  94. int n, m;
  95. while (scanf("%d%d", &n, &m) != EOF) {
  96. build(, , n);
  97. while (m--) {
  98. int opt, x, y;
  99. scanf("%d", &opt);
  100. if (opt == ) {
  101. scanf("%d", &x);
  102. if (tree[].max < x) {
  103. printf("0\n");
  104. continue;
  105. }
  106. int ans = query(, x);
  107. if (ans) update(, ans, ans + x - , );
  108. printf("%d\n", ans);
  109. }
  110. else {
  111. scanf("%d%d", &x, &y);
  112. update(, x, x + y - , );
  113. }
  114. }
  115. }
  116. return ;
  117. }

线段树

 

G - 约会安排

这个题目 :

如果是 DS 就是普通的查找,如果找到就输出最靠前的时间点,这个和上面的操作很像,然后更新。

如果是 NS 就要进行两次查找,第一次是普通查找,没有找到就是二级查找,这个二级查找就是一种覆盖,然后更新。

如果是 study 那就是清空为0 的操作。

这个就是相当于建了两棵树,一颗女神树,一颗基友树,处理女神树的时候要更新基友树,但是处理基友树就不需要更新女神树。

这个题目一定要注意 输出答案

描述中的“如果找到,就说“X,let’s fly”(此处,X为开始时间)…"
和Output中的 “X,let's fly”
里的“ ’ ”和 “ ' ” 不是一个符号,别复制错了!!!

  1. #include <cstdio>//描述中的“如果找到,就说“X,let’s fly”(此处,X为开始时间)…"
  2. #include <cstdlib>//和Output中的 “X, let's fly”
  3. #include <cstring>//里的“ ’ ”和 “ ' ” 不是一个符号,别复制错了!!!
  4. #include <queue>
  5. #include <vector>
  6. #include <algorithm>
  7. #include <string>
  8. #include <stack>
  9. #include <iostream>
  10. #include <map>
  11. #define inf 0x3f3f3f3f
  12. #define inf64 0x3f3f3f3f3f3f3f3f
  13. using namespace std;
  14. const int maxn = 1e5 + ;
  15. typedef long long ll;
  16. struct node {
  17. int len;
  18. int lsum, rsum, sum;//1 级的
  19. int lmax, rmax, max;//2 级的
  20. }tree[maxn * ];
  21.  
  22. void build(int id, int l, int r) {
  23. tree[id].max = tree[id].lmax = tree[id].rmax = r - l + ;
  24. tree[id].len = tree[id].lsum = tree[id].rsum = tree[id].sum = r - l + ;
  25. if (l == r) return;
  26. int mid = (l + r) >> ;
  27. build(id << , l, mid);
  28. build(id << | , mid + , r);
  29. }
  30.  
  31. void push_up(int id) {
  32. tree[id].lsum = tree[id << ].lsum;
  33. tree[id].rsum = tree[id << | ].rsum;
  34. if (tree[id << ].lsum == tree[id << ].len) tree[id].lsum += tree[id << | ].lsum;
  35. if (tree[id << | ].rsum == tree[id << | ].len) tree[id].rsum += tree[id << ].rsum;
  36. tree[id].sum = max(max(tree[id << ].sum, tree[id << | ].sum), tree[id << ].rsum + tree[id << | ].lsum);
  37. tree[id].sum = max(tree[id].sum, tree[id].lsum);
  38. tree[id].sum = max(tree[id].sum, tree[id].rsum);
  39.  
  40. tree[id].lmax = tree[id << ].lmax;
  41. tree[id].rmax = tree[id << | ].rmax;
  42. if (tree[id << ].lmax == tree[id << ].len) tree[id].lmax += tree[id << | ].lmax;
  43. if (tree[id << | ].rmax == tree[id << | ].len) tree[id].rmax += tree[id << ].rmax;
  44. tree[id].max = max(max(tree[id << ].max, tree[id << | ].max), tree[id << ].rmax + tree[id << | ].lmax);
  45. tree[id].max = max(tree[id].max, tree[id].lmax);
  46. tree[id].max = max(tree[id].max, tree[id].rmax);
  47. }
  48.  
  49. void push_down(int id) {
  50. if(tree[id].max==tree[id].len)
  51. {
  52. tree[id << ].max = tree[id << ].lmax = tree[id << ].rmax = tree[id << ].len;
  53. tree[id << | ].max = tree[id << | ].lmax = tree[id << | ].rmax = tree[id << | ].len;
  54. }
  55. if(tree[id].max==)
  56. {
  57. tree[id << ].max = tree[id << ].lmax = tree[id << ].rmax = ;
  58. tree[id << | ].max = tree[id << | ].lmax = tree[id << | ].rmax = ;
  59. }
  60. if(tree[id].sum==tree[id].len)
  61. {
  62. tree[id << ].sum = tree[id << ].lsum = tree[id << ].rsum = tree[id << ].len;
  63. tree[id << | ].sum = tree[id << | ].lsum = tree[id << | ].rsum = tree[id << | ].len;
  64. }
  65. if(tree[id].sum==)
  66. {
  67. tree[id << ].sum = tree[id << ].lsum = tree[id << ].rsum = ;
  68. tree[id << | ].sum = tree[id << | ].lsum = tree[id << | ].rsum = ;
  69. }
  70. }
  71.  
  72. void update(int id, int l, int r, int x, int y, int val) {
  73. if (x <= l && y >= r) {
  74. if (val == ) {
  75. tree[id].max = tree[id].lmax = tree[id].rmax = ;
  76. tree[id].sum = tree[id].lsum = tree[id].rsum = ;
  77. }
  78. if (val == ) {
  79. tree[id].sum = tree[id].lsum = tree[id].rsum = ;
  80. }
  81. if (val == ) {
  82. tree[id].max = tree[id].lmax = tree[id].rmax = tree[id].len;
  83. tree[id].sum = tree[id].lsum = tree[id].rsum = tree[id].len;
  84. }
  85. return;
  86. }
  87. push_down(id);
  88. int mid = (l + r) >> ;
  89. if (x <= mid) update(id << , l, mid, x, y, val);
  90. if (y > mid) update(id << | , mid + , r, x, y, val);
  91. push_up(id);
  92. }
  93.  
  94. int query_1(int id, int l, int r, int val) {
  95. if (l == r) return l;
  96. int mid = (l + r) >> ;
  97. push_down(id);
  98. if (tree[id << ].sum >= val) return query_1(id << , l, mid, val);
  99. if (tree[id << ].rsum + tree[id << | ].lsum >= val) return mid - tree[id << ].rsum + ;
  100. return query_1(id << | , mid + , r, val);
  101. }
  102.  
  103. int query_2(int id,int l,int r,int val)
  104. {
  105. if (l == r) return l;
  106. int mid = (l + r) >> ;
  107. push_down(id);
  108. if (tree[id << ].max >= val) return query_2(id << , l, mid, val);
  109. if (tree[id << ].rmax + tree[id << | ].lmax >= val) return mid - tree[id << ].rmax + ;
  110. return query_2(id << | , mid + , r, val);
  111. }
  112.  
  113. int main()
  114. {
  115. int t;
  116. scanf("%d", &t);
  117. for(int cas=;cas<=t;cas++)
  118. {
  119. int n, m, x, y;
  120. scanf("%d%d", &n, &m);
  121. build(, , n);
  122. printf("Case %d:\n", cas);
  123. while(m--)
  124. {
  125. char s[];
  126. scanf("%s", s);
  127. if(s[]=='D')
  128. {
  129. scanf("%d", &x);
  130. if(tree[].sum<x)
  131. {
  132. printf("fly with yourself\n");
  133. continue;
  134. }
  135. int ans = query_1(, , n, x);
  136. printf("%d,let's fly\n", ans);
  137. update(, , n, ans, x + ans - , );
  138. }
  139. if(s[]=='N')
  140. {
  141. scanf("%d", &x);
  142. if(tree[].sum>=x)
  143. {
  144. int ans = query_1(, , n, x);
  145. printf("%d,don't put my gezi\n", ans);
  146. update(, , n, ans, x + ans - , );
  147. continue;
  148. }
  149. if(tree[].max<x)
  150. {
  151. printf("wait for me\n");
  152. continue;
  153. }
  154. int ans = query_2(,,n,x);
  155. printf("%d,don't put my gezi\n", ans);
  156. update(, , n, ans, x + ans - , );
  157. }
  158. if(s[]=='S')
  159. {
  160. scanf("%d%d", &x, &y);
  161. update(, , n, x, y, );
  162. printf("I am the hope of chinese chengxuyuan!!\n");
  163. }
  164. }
  165. }
  166. }

线段树

E - Tunnel Warfare HDU - 1540 F - Hotel G - 约会安排 HDU - 4553 区间合并的更多相关文章

  1. hdu 4453 约会安排(线段树区间合并)

    约会安排 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submis ...

  2. M - 约会安排 - hdu 4553

    寒假来了,又到了小明和女神们约会的季节.  小明虽为�丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会.与此同时,也有很多基友找他开黑,由于数量 ...

  3. 约会安排HDU - 4553

    寒假来了,又到了小明和女神们约会的季节.  小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复"呵呵",所以,小明的最爱就是和女神们约会.与此同时,也有很多基 ...

  4. M - 约会安排 HDU - 4553 线段树 (最长连续段)

    中文题面 思路:维和两个区间  一个是女神区间 一个是基友区间  如果是基友要预约时间 直接在基友区间查询可满足的起点 (这里先判tree[1].m >=length也就是有没有这样的区间满足时 ...

  5. HDU 3308 LCIS (线段树&#183;单点更新&#183;区间合并)

    题意  给你一个数组  有更新值和查询两种操作  对于每次查询  输出相应区间的最长连续递增子序列的长度 基础的线段树区间合并  线段树维护三个值  相应区间的LCIS长度(lcis)  相应区间以左 ...

  6. 约会安排 HDU - 4553(线段树区间查询,区间修改,区间合并)

    题目: 寒假来了,又到了小明和女神们约会的季节.  小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会.与此同时,也有很多基友找他开黑, ...

  7. HDU 3911 线段树区间合并、异或取反操作

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...

  8. hdu 1540 Tunnel Warfare 线段树 单点更新,查询区间长度,区间合并

    Tunnel Warfare Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...

  9. hdu 1540 Tunnel Warfare (区间线段树(模板))

    http://acm.hdu.edu.cn/showproblem.php?pid=1540 Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) ...

随机推荐

  1. Git应用详解第九讲:Git cherry-pick与Git rebase

    前言 前情提要:Git应用详解第八讲:Git标签.别名与Git gc 这一节主要介绍git cherry-pick与git rebase的原理及使用. 一.Git cherry-pick Git ch ...

  2. 记一个openwrt reboot异步信号处理死锁问题

    写在前面 觉得本页面排版单调的话,可以尝试到这里看. 问题背景 在 openwrt 上碰到了一个偶现的 reboot 失效问题.执行 reboot 之后系统并没有重启,此时控制台还能工作. 初步排查 ...

  3. L21 Momentum RMSProp等优化方法

    airfoil4755 下载 链接:https://pan.baidu.com/s/1YEtNjJ0_G9eeH6A6vHXhnA 提取码:dwjq 11.6 Momentum 在 Section 1 ...

  4. PHP Curl 请求https 60错误解决办法

      curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); 

  5. Java 排序算法-冒泡排序及其优化

    Java 排序算法-冒泡排序及其优化 什么是冒泡排序 基本写法 优化后写法 终极版本 源码及测试 什么是冒泡排序 这里引用一下百度百科上的定义: 冒泡排序(Bubble Sort),是一种计算机科学领 ...

  6. ubuntu安装Python3并与Python2自由切换

    一.配置ssh链接安装openssh-server sudo apt-get install openssh-server 二.安装Python3及pip sudo apt-get install p ...

  7. 0day笔记(1)PE文件格式与虚拟文件内存的映射

    PE文件格式 PE 文件格式把可执行文件分成若干个数据节(section),不同的资源被存放在不同的节中. 一个典型的 PE 文件中包含的节如下: .text 存放着二进制的机器代码 .data 初始 ...

  8. php 推荐密码加密的方法

    password_hash() 函数 password_hash() 函数用于创建密码的散列(hash) PASSWORD_DEFAULT - 使用 bcrypt 算法 (PHP 5.5.0 默认). ...

  9. thinkphp5.0 模型的应用

    <?php namespace app\admin\controller; use app\common\controller\BaseController; use think\Db;//数据 ...

  10. JS 获取GET 参数

    对于 URL,我们需要了解更多,因为我们的开发中可能会需要提取URL的部分信息来做不同的事情,事实上这也是与后端交互的一种独特的方式,当然这肯定是安全的,当请求被返回,关于 url 的信息就被记录在了 ...