B - Tunnel WarfareHDU - 1540
这个有两种方法,一个是区间和并,这个我个人感觉异常恶心
第二种方法就是找最大最小值 kuangbin——线段树专题 H - Tunnel Warfare <-- 这个博客讲的很清楚
#include <cstdio>//法一:最大值最小值法,这个就是每一个点,如果这个点没有被摧毁,那就找到这个点最左边的和最右边的 #include <cstdlib>//最大-最小+1.这个就是这个最大连续长度。 #include <queue>//建树,很简单,主要就是query和update。 #include <algorithm>//这个地方的怎么去找一个包含一个数的一个区间的最大最小值呢? #include <vector>//这个就是从上面往下面查询的过程中,就去找,如果是找最大值就去max,最小值就取min #include <cstring>//这个要注意建树,这个区间的最大值的意思是,小于等于这个数的最大的被炸了的村庄,这个就说明,开始最大值为0,因为没有任何一个村庄被炸 #include <string>//区间的最小值,意思是大于等于这个数,被炸了的村庄的最小值,开始为n+1.因为没有村庄被炸。 #include <iostream> #include <stack> #define inf 0x3f3f3f3f using namespace std; const int maxn = 1e5 + 100; struct node { int l, r; int mx, mn; }tree[maxn*4]; int n; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; if(l==r) { tree[id].mn = n+1; tree[id].mx = 0; return; } int mid = (l + r) >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); tree[id].mx = max(tree[id << 1].mx, tree[id << 1 | 1].mx); tree[id].mn = min(tree[id << 1].mn, tree[id << 1 | 1].mn); } void update_max(int id,int x,int z) { if(tree[id].l==tree[id].r) { tree[id].mx = z; return; } int mid = (tree[id].l + tree[id].r) >> 1; if(x<=mid) update_max(id << 1, x, z); if (x > mid) update_max(id << 1 | 1, x, z); tree[id].mx = max(tree[id << 1].mx, tree[id << 1 | 1].mx); } void update_min(int id,int x,int z) { if(tree[id].l==tree[id].r) { tree[id].mn = z; return; } int mid = (tree[id].l + tree[id].r) >> 1; if (x <= mid) update_min(id << 1, x, z); if (x > mid) update_min(id << 1 | 1, x, z); tree[id].mn = min(tree[id << 1].mn, tree[id << 1 | 1].mn); } int query_max(int id,int x,int y) { int ans = 0; if(x<=tree[id].l&&y>=tree[id].r) { return tree[id].mx; } int mid = (tree[id].l + tree[id].r) >> 1; if (x <= mid) ans = max(ans, query_max(id << 1, x, y)); if (y > mid) ans = max(ans, query_max(id << 1 | 1, x, y)); return ans; } int query_min(int id,int x,int y) { int ans = inf; if(x<=tree[id].l&&y>=tree[id].r) { return tree[id].mn; } int mid = (tree[id].l + tree[id].r) >> 1; if (x <= mid) ans = min(ans, query_min(id << 1, x, y)); if (y > mid) ans = min(ans, query_min(id << 1 | 1, x, y)); return ans; } int main() { int m, x; while(cin >> n >> m) { stack<int>sta; build(1, 1, n); while(m--) { char s[10]; scanf("%s", s); if(s[0]=='D') { cin >> x; update_max(1, x, x); update_min(1, x, x); sta.push(x); } if(s[0]=='R') { int y = sta.top(); sta.pop(); update_max(1, y, 0); update_min(1, y, n + 1); } if(s[0]=='Q') { cin >> x; int L = query_min(1, x, n + 1); int R = query_max(1, 0, x); //printf("%d %d\n", L, R); if (L == R) printf("0\n"); else printf("%d\n", L - R - 1); } } } return 0; }
//法二:区间合并,这个应该更好懂一点,就是维护一下一个区间的前缀后缀长度 //这个更新应该比较简单, #include <cstdio> #include <cstdlib> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <string> #include <iostream> #include <stack> #define inf 0x3f3f3f3f using namespace std; const int maxn = 1e5 + 100; struct node { int l, r, len; int max_pre, max_last; }tree[maxn*4]; void push_up(int id) { tree[id].max_pre = tree[id << 1].max_pre; tree[id].max_last = tree[id << 1 | 1].max_last; if (tree[id << 1].max_pre == tree[id << 1].len) { tree[id].max_pre += tree[id << 1 | 1].max_pre; } if(tree[id<<1|1].max_last==tree[id<<1|1].len) { tree[id].max_last += tree[id << 1].max_last; } } void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].len = r - l + 1; if(l==r) { tree[id].max_pre = tree[id].max_last = 1; return; } int mid = (l + r) >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); push_up(id); } void update(int id,int x,int z) { if(tree[id].l==tree[id].r) { tree[id].max_pre = z; tree[id].max_last = z; return; } int mid = (tree[id].l + tree[id].r) >> 1; if (x <= mid) update(id << 1, x, z); else update(id << 1 | 1, x, z); push_up(id); } int query_pre(int id,int x,int y) { int ans = 0, res = 0; if(x<=tree[id].l&&y>=tree[id].r) { //printf("tree[%d].max_pre=%d\n", id, tree[id].max_pre); return tree[id].max_pre; } //printf("id=%d x=%d y=%d\n", id, x, y); int mid = (tree[id].l + tree[id].r) >> 1; if (x <= mid) ans=query_pre(id << 1, x, y); if (y > mid) res=query_pre(id << 1 | 1, x, y); //printf("id=%d ans=%d res=%d mid=%d\n",id, ans, res,mid); if (ans >= mid - x + 1) { //printf("tree[%d].max_pre=%d mid=%d x=%d\n",id, tree[id].max_pre, mid, x); ans += res; } return ans; } int query_last(int id,int x,int y) { int ans = 0, res = 0; if (x <= tree[id].l&&y >= tree[id].r) { //printf("tree[%d].last=%d\n", id, tree[id].max_last); return tree[id].max_last; } //printf("id=%d x=%d y=%d\n", id, x, y); int mid = (tree[id].l + tree[id].r) >> 1; if (x <= mid) ans = query_last(id << 1, x, y); if (y > mid) res = query_last(id << 1 | 1, x, y); //printf("id=%d mid=%d ans=%d res=%d\n", id, mid,ans, res); if (res >= y-mid) { //printf("tree[%d].max_last=%d mid=%d x=%d\n",id,tree[id].max_last, mid, x); res += ans; } return res; } int main() { int n, m; while(scanf("%d %d",&n,&m)!=EOF) { stack<int>sta; build(1, 1, n); while(m--) { char s[10]; scanf("%s", s); if(s[0]=='D') { int x; cin >> x; update(1, x, 0); sta.push(x); } if(s[0]=='R') { int y = sta.top(); sta.pop(); update(1, y, 1); } if(s[0]=='Q') { int x; cin >> x; int ans = query_pre(1, x, n); ans += query_last(1, 1, x); if(ans) printf("%d\n", ans-1); else printf("0\n"); } } } return 0; } /* 7 10 D 3 D 6 D 5 Q 4 Q 5 R Q 4 R Q 4 Q 3 */
来源:https://www.cnblogs.com/EchoZQN/p/10802782.html