线段树 (区间覆盖模板)

线段树

  线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
  对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。
  使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。

题目链接:  http://acm.zzuli.edu.cn/zzuliacm/problem.php?id=1877

代码:

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <cstring>
  4 #include <string>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <stack>
  8 #include <map>
  9 #include <set>
 10 #include <vector>
 11 #include <iostream>
 12 using namespace std;
 13 #define for0(i, n) for(int i=0; i<(n); ++i)
 14 #define for1(i,a,n) for(int i=(a);i<=(n);++i)
 15 #define for2(i,a,n) for(int i=(a);i<(n);++i)
 16 #define for3(i,a,n) for(int i=(a);i>=(n);--i)
 17 #define for4(i,a,n) for(int i=(a);i>(n);--i)
 18 #define CC(i,a) memset(i,a,sizeof(i))
 19 #define LL long long
 20 #define MOD 1000000007
 21 #define inf 0x3f3f3f3f
 22
 23 #define EPS 1e-6
 24 #define N 100010
 25 #define lson p<<1
 26 #define rson p<<1|1
 27
 28 struct num
 29 {
 30     int l,r;
 31 }a[N];
 32 int v[N];
 33
 34 struct node
 35 {
 36     int l,r,x;
 37     int mid(){
 38         return (l+r)/2;
 39     }
 40     int len(){
 41         return (r-l+1);
 42     }
 43 }tree[N<<2];
 44
 45 void buildtree(int p,int L,int R)
 46 {
 47     tree[p].l=L;
 48     tree[p].r=R;
 49     tree[p].x=0;
 50     if(L==R)
 51         return ;
 52
 53     buildtree(lson,L,tree[p].mid());
 54     buildtree(rson,tree[p].mid()+1,R);
 55 }
 56
 57 void update(int p,int L,int R)
 58 {
 59     if(tree[p].l==L && tree[p].r==R){
 60         tree[p].x++;
 61         return ;
 62     }
 63     if(R <= tree[p].mid())
 64         update(lson,L,R);
 65     else if(L > tree[p].mid())
 66         update(rson,L,R);
 67     else{
 68         update(lson,L,tree[p].mid());
 69         update(rson,tree[p].mid()+1,R);
 70     }
 71 }
 72
 73 void up(int p,int L,int R)
 74 {
 75     if(L==R)
 76         return ;
 77     tree[lson].x += tree[p].x;
 78     tree[rson].x += tree[p].x;
 79
 80     up(lson,L,tree[p].mid());
 81     up(rson,tree[p].mid()+1,R);
 82
 83     tree[p].x = min(tree[lson].x,tree[rson].x);
 84 }
 85
 86 int query(int p,int L,int R)
 87 {
 88     if(tree[p].l==L && tree[p].r==R)
 89         return tree[p].x;
 90     if(R <= tree[p].mid())
 91         return query(lson,L,R);
 92     else if(L > tree[p].mid())
 93         return query(rson,L,R);
 94     else
 95         return min(query(lson,L,tree[p].mid()),query(rson,tree[p].mid()+1,R));
 96
 97 }
 98
 99 int main()
100 {
101     int t;
102     scanf("%d",&t);
103     while(t--){
104         int n,m,k=0,ans;
105         scanf("%d%d",&n,&m);
106         memset(a,0,sizeof(a));
107         memset(v,0,sizeof(v));
108         buildtree(1,1,n);
109
110         for(int i=1; i<=m; i++){
111             scanf("%d%d",&a[i].l,&a[i].r);
112             update(1,a[i].l,a[i].r);
113         }
114
115         up(1,1,n);
116
117         for(int i=1; i<=m; i++){
118             ans=query(1,a[i].l,a[i].r);
119             if(ans >= 2)
120                 v[k++] = i;
121         }
122         printf("%d\n", k);
123         for(int i=0; i<k; i++)
124             printf("%d%c", v[i], i==k-1?‘\n‘:‘ ‘);
125     }
126     return 0;
127 }

另外的版本:  https://hrbust-acm-team.gitbooks.io/acm-book/content/data_structure/ds_part3.html

时间: 2024-11-05 00:15:11

线段树 (区间覆盖模板)的相关文章

HDU 4509 湫湫系列故事——减肥记II(线段树-区间覆盖 或者 暴力技巧)

http://acm.hdu.edu.cn/showproblem.php?pid=4509 题目大意: 中文意义,应该能懂. 解题思路: 因为题目给的时间是一天24小时,而且还有分钟.为了解题方便,我们将小时换成分钟,那么一天24小时,总共有1440分钟.顾我就可以把一天里的任意HH:MM时间换成分钟.就这样一天的时间就变成[0,1440]区间了. 因为所给的活动最多是5*10^5,如果把活动的时间在线段[0,1440]都修改,那么时间的复杂度最坏是O(5*10^5*1440). (1)方法一

线段树 + 区间更新 + 模板 ---- poj 3468

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 59798   Accepted: 18237 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

hdu1698(线段树区间替换模板)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1698 题意: 第一行输入 t 表 t 组测试数据, 对于每组测试数据, 第一行输入一个 n , 表示钩子有 n 节, 编号为 1 ~ n, 每节钩子的初始价值为 1 , 接下来输入一个 q, 接着 q 行输入, 每行格式为 l, r, x, 表示讲区间 [l, r] 内的钩子价值变成 x , 求最终的总价值: 思路: 线段树区间替换模板 代码: 1 #include <iostream> 2 #

poj 2528 Mayor&#39;s posters(线段树区间覆盖、离散化)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 49385   Accepted: 14304 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

Mayor&#39;s posters 线段树区间覆盖

题目链接 http://poj.org/problem?id=2528 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally dec

POJ - 2528Mayor&#39;s posters (离散化+线段树区间覆盖)

The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for placing the

Mayor&#39;s posters POJ - 2528 线段树区间覆盖

//线段树区间覆盖 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=100010; int flag; struct node{ int l,r; //vis 是这块区域是否完全被覆盖 bool vis; }tr[N<<2]; struct point { int id; int x

线段树区间修改模板

本来打算把大白书第三章一口气攻下来的,但是这个线段树也是卡了好久. 不敢过题太快,怕自己走马观花到头来结果什么都不会. 可也不能再拖了,在做题中也许有更多的体会. 模板一:1 L R v 表示区间[L, R]所有元素都加上v2 L R   表示查询区间[L, R]的sum, min, maxsumv[o]的定义为:如果只执行节点o及其子孙节点的中的add操作,节点o对应区间中所有数之和 1 //线段树区间修改 2 //1 L R v 表示区间[L, R]所有元素都加上v 3 //2 L R 表示

POJ-3468 - A Simple Problem with Integers(线段树区间更新模板)

http://poj.org/problem?id=3468 Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of