线段树几题 --------- 成段更新
来源:互联网 发布:手机电信4g网络被劫持 编辑:程序博客网 时间:2024/06/06 02:31
线段树的成段更新,需要用到延迟标记
就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候
否则就会退化到O(n)的复杂度
1.hdu 1698 Just a Hook
大意是每次把某一段所有数的值改变成某个值,最后求总和。
#include <iostream>#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <cstring>#include <cmath>#include <ctime>#define MAXN 100005#define INF 100000000#define eps 1e-11#define L(x) x<<1#define R(x) x<<1|1using namespace std;struct node{ int left, right, mid; int cover, len, sum;}tree[4 * MAXN];void make_tree(int s, int e, int C){ tree[C].left = s; tree[C].right = e; tree[C].mid = (s + e) / 2; tree[C].len = tree[C].right - tree[C].left + 1; tree[C].cover = 1; tree[C].sum = tree[C].cover * tree[C].len; if(s == e) return; make_tree(s, tree[C].mid, L(C)); make_tree(tree[C].mid + 1, e, R(C));}void up(int C){ tree[C].sum = tree[L(C)].sum + tree[R(C)].sum;}void down(int C){ if(tree[C].cover) { tree[L(C)].cover = tree[R(C)].cover = tree[C].cover; tree[L(C)].sum = tree[L(C)].len * tree[L(C)].cover; tree[R(C)].sum = tree[R(C)].len * tree[R(C)].cover; tree[C].cover = 0; }}void update(int s, int e, int k, int C){ if(tree[C].left >= s && tree[C].right <= e) { tree[C].cover = k; tree[C].sum = tree[C].cover * tree[C].len; return; } down(C); if(tree[C].mid < s) update(s, e, k, R(C)); else if(tree[C].mid >= e) update(s, e, k, L(C)); else { update(s, tree[C].mid, k, L(C)); update(tree[C].mid + 1, e, k, R(C)); } up(C);}int main(){ //freopen("d:/data.in","r",stdin); //freopen("d:/data.out","w",stdout); int t, n, i, x, y, z, cas = 0, m; scanf("%d", &t); while(t--) { scanf("%d", &n); make_tree(1, n, 1); scanf("%d", &m); for(i = 0; i < m; i++) { scanf("%d%d%d", &x, &y, &z); update(x, y, z, 1); } printf("Case %d: The total value of the hook is %d.\n", ++cas, tree[1].sum); } return 0;}
2. POJ 3468 A Simple Problem with Integers
这题比上面那道的操作稍微复杂了一点,把某个区间的数统一加上某个值。
#include <iostream>#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <cstring>#include <cmath>#include <ctime>#define MAXN 100005#define INF 100000000#define eps 1e-11#define L(x) x<<1#define R(x) x<<1|1using namespace std;struct node{ int left, right, mid; __int64 cover, len; __int64 sum;}tree[4 * MAXN];__int64 a[100005];void up(int C){ tree[C].sum = tree[L(C)].sum + tree[R(C)].sum;}void down(int C){ if(tree[C].cover) { tree[L(C)].cover += tree[C].cover; tree[R(C)].cover += tree[C].cover; tree[L(C)].sum += tree[C].cover * tree[L(C)].len; tree[R(C)].sum += tree[C].cover * tree[R(C)].len; tree[C].cover = 0; }}void make_tree(int s, int e, int C){ tree[C].left = s; tree[C].right = e; tree[C].mid = (s + e) / 2; tree[C].cover = 0; tree[C].sum = 0; tree[C].len = tree[C].right - tree[C].left + 1; if(s == e) { tree[C].sum = a[s]; return; } make_tree(s, tree[C].mid, L(C)); make_tree(tree[C].mid + 1, e, R(C)); up(C);}void update(int s, int e, __int64 k, int C){ if(tree[C].left >= s && tree[C].right <= e) { tree[C].cover += k; tree[C].sum += k * tree[C].len; return; } down(C); if(tree[C].mid < s) update(s, e, k, R(C)); else if(tree[C].mid >= e) update(s, e, k, L(C)); else { update(s, tree[C].mid, k, L(C)); update(tree[C].mid + 1, e, k, R(C)); } up(C);}__int64 query(int s, int e, int C){ if(tree[C].left >= s && tree[C].right <= e) return tree[C].sum; down(C); __int64 tmp = 0; if(tree[C].mid < s) tmp += query(s, e, R(C)); else if(tree[C].mid >= e) tmp += query(s, e, L(C)); else { tmp += query(s, tree[C].mid, L(C)); tmp += query(tree[C].mid + 1, e, R(C)); } return tmp;}int main(){ //freopen("d:/data.in","r",stdin); //freopen("d:/data.out","w",stdout); int n, m, i, x, y; __int64 z; char s[5]; scanf("%d%d", &n, &m); for(i = 1; i <= n; i++) scanf("%I64d", &a[i]); make_tree(1, n, 1); while(m--) { scanf("%s", s); if(s[0] == 'Q') { scanf("%d%d", &x, &y); printf("%I64d\n",query(x, y, 1)); } else if(s[0] == 'C') { scanf("%d%d%I64d", &x, &y, &z); update(x, y, z, 1); } } return 0;}
3.poj 2528 Mayor’s posters
大意就是往墙上按区间涂色,看最后能看见的颜色个数
比较麻烦的就是离散化的事情,先把所有的坐标存下来,去重后映射一下,这时就有些问题了,比如原始坐标是1, 3, 6, 10,映射完了是0, 1, 2, 3,3和6本来中间还有几块的,离散完了成相邻的了,所以这里就要处理一下,1,3,6, 10就要处理成1,2,3,4,6,7,10之类的,总之相邻的坐标之差如果大于1了,就在中间添加一个适当的数表示这之间还有块。
然后就建线段树,查询的时候查整个线段树中颜色的个数就行了。
#include <iostream>#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <cstring>#include <cmath>#include <ctime>#define MAXN 10005#define INF 100000000#define eps 1e-11#define L(x) x<<1#define R(x) x<<1|1using namespace std;struct node{ int left, right, mid; int cover;}tree[16 * MAXN];int a[4 * MAXN];int l[MAXN];int r[MAXN];int ans, n;bool used[MAXN];void make_tree(int s, int e, int C){ tree[C].left = s; tree[C].right = e; tree[C].cover = -1; tree[C].mid = (s + e) / 2; if(s == e) return; make_tree(s, tree[C].mid, L(C)); make_tree(tree[C].mid + 1, e, R(C));}void down(int C){ if(tree[C].cover != -1) { tree[L(C)].cover = tree[R(C)].cover = tree[C].cover; tree[C].cover = -1; }}void update(int s, int e, int k, int C){ if(tree[C].left >= s && tree[C].right <= e) { tree[C].cover = k; return; } down(C); if(tree[C].mid < s) update(s, e, k, R(C)); else if(tree[C].mid >= e) update(s, e, k, L(C)); else { update(s, tree[C].mid, k, L(C)); update(tree[C].mid + 1, e, k, R(C)); }}void query(int C){ if(tree[C].cover != -1) { if(!used[tree[C].cover]) { ans++; used[tree[C].cover] = 1; } return; } if(tree[C].left == tree[C].right) return; query(L(C)); query(R(C));}int b_search(int v){ int left = 0, right = n - 1; while(left <= right) { int mid = (left + right) / 2; if(a[mid] == v) return mid; else if(a[mid] > v) right = mid - 1; else left = mid + 1; } return 0;}int main(){ //freopen("d:/data.in","r",stdin); //freopen("d:/data.out","w",stdout); int t, m, i; scanf("%d", &t); while(t--) { ans = 0; memset(used, 0, sizeof(used)); scanf("%d", &m); int cnt = 0; for(i = 0; i < m; i++) { scanf("%d%d", &l[i], &r[i]); a[cnt++] = l[i]; a[cnt++] = r[i]; } sort(a, a + cnt); n = unique(a, a + cnt) - a; for(i = n - 1; i > 0; i--) { if(a[i] - a[i - 1] != 1) a[n++] = a[i - 1] + 1; } sort(a, a + n); n = unique(a, a + n) - a; make_tree(0, n - 1, 1); for(i = 0; i < m; i++) { int ll = b_search(l[i]); //printf("ll %d\n", ll); int rr = b_search(r[i]); update(ll, rr, i, 1); //printf("rr %d\n", rr); } query(1); printf("%d\n", ans); } return 0;}
然后更神的是这道题可以用并查集做
从acmol的空间看的http://blog.acmol.com/?p=751
/*ID: sdj22251PROG: inflateLANG: C++*/#include <iostream>#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <cstring>#include <cmath>#include <ctime>#define MAXN 9*9*9*9#define INF 1000000000using namespace std;int hash[10000005];int father[40005];int a[10005], b[10005], x[20005];bool v[40005];int find(int x){ if(father[x] == -1) return x; int t = find(father[x]); father[x] = t; return t;}int main(){ int T, n; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%d%d", &a[i], &b[i]); x[2 * i] = a[i]; x[2 * i + 1] = b[i]; } sort(x, x + 2 * n); int cnt = unique(x, x + 2 * n) - x; hash[x[0]] = 0; for(int i = 1; i < cnt; i++) { int flag = 0; if(x[i - 1] + 1 != x[i]) flag = 1; hash[x[i]] = hash[x[i - 1]] + flag + 1; } int ans = 0; memset(v, 0, sizeof(v)); memset(father, -1, sizeof(father)); for(int i = n - 1; i >= 0; i--) { bool flag = false; int fa = find(hash[a[i]]), fb; for(int j = hash[b[i]]; j >= hash[a[i]]; j = fb - 1) { fb = find(j); if(!v[fb]) v[fb] = flag = true; if(fa != fb) father[fb] = fa; } if(flag) ans++; } printf("%d\n", ans); } return 0;}
4.POJ 2777 Count Color
几乎与2528一摸一样的题,只不过更加裸了
#include <iostream>#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <cstring>#include <cmath>#include <ctime>#define MAXN 100005#define INF 100000000#define eps 1e-11#define L(x) x<<1#define R(x) x<<1|1using namespace std;struct node{ int left, right, mid; int cover;}tree[4 * MAXN];bool used[33];int ans;void make_tree(int s, int e, int C){ tree[C].left = s; tree[C].right = e; tree[C].cover = 1; tree[C].mid = (s + e) / 2; if(s == e) return; make_tree(s, tree[C].mid, L(C)); make_tree(tree[C].mid + 1, e, R(C));}void down(int C){ if(tree[C].cover != -1) { tree[L(C)].cover = tree[R(C)].cover = tree[C].cover; tree[C].cover = -1; }}void update(int s, int e, int k, int C){ if(tree[C].left >= s && tree[C].right <= e) { tree[C].cover = k; return; } down(C); if(tree[C].mid < s) update(s, e, k, R(C)); else if(tree[C].mid >= e) update(s, e, k, L(C)); else { update(s, tree[C].mid, k, L(C)); update(tree[C].mid + 1, e, k, R(C)); }}void query(int s, int e, int C){ if(tree[C].cover != -1) { if(!used[tree[C].cover]) { ans++; used[tree[C].cover] = 1; } return; } if(tree[C].left == tree[C].right) return; if(tree[C].mid < s) query(s, e, R(C)); else if(tree[C].mid >= e) query(s, e, L(C)); else { query(s, tree[C].mid, L(C)); query(tree[C].mid + 1, e, R(C)); }}int main(){ //freopen("d:/data.in","r",stdin); //freopen("d:/data.out","w",stdout); int n, m, t, x, y, z, i; char s[5]; scanf("%d%d%d", &n, &m, &t); make_tree(1, n, 1); while(t--) { scanf("%s", s); if(s[0] == 'C') { scanf("%d%d%d", &x, &y, &z); if(x > y) swap(x, y); update(x, y, z, 1); } else { scanf("%d%d", &x, &y); ans = 0; memset(used, 0, sizeof(used)); query(x, y, 1); printf("%d\n", ans); } } return 0;}
- 线段树几题 --------- 成段更新
- 线段树 成段更新
- 线段树 成段更新
- 线段树 成段更新
- 线段树 成段更新 hdu1698
- hdu 1698 线段树 成段更新
- poj 3468 线段树 成段更新
- hdu 4325 线段树 成段更新
- hdu 4107 线段树 成段更新
- 线段树HDU1698(成段更新)
- HDU 4027 ( 线段树 -- 成段更新)
- UVA11992----线段树的成段更新
- hdu 3577 线段树,成段更新
- hdu 1698 线段树-成段更新
- poj 3468 线段树--成段更新
- 线段树 (成段更新)
- poj 2528 线段树--成段更新
- hdu 4902 线段树-成段更新
- 工作学习笔记——CSAPP第三章
- 分享2011年50个最棒的wordpress主题
- select 效率问题
- J-LINK烧写不进uboot时的问题
- GBin1随机分享的10个使用简单的插件
- 线段树几题 --------- 成段更新
- 成功路上的关键5步
- 用link方法安装Eclipse插件(Windows和Ubuntu都适用)
- 体验Git,Github
- 深入浅出之正则表达式(一)
- 《鸟哥的linux》-第14章-linux账号与身份管理
- USACO Section 3.2 PROB Spinning Wheels
- 子衿的事(50)
- linux 串口驱动测试代码