题目
晚上有n个亮着的灯泡,标号从1到n。
现在存在2种操作,如下:
- 操作1,关掉标号 [l,r] 区间的灯
- 操作2,打开标号 [l,r] 区间的灯
下面有q次询问,每次询问执行其中一种操作,询问格式,l,r,k,k为执行操作种类。对于每次询问回答当前开着的灯的数量。
Input
单组输入,第一行包含一个整数n,第二行一个整数q(1≤n≤10^9,1≤q≤3·10^5)
接下来q行每行3个整数表示询问,l,r,k(1 ≤ l ≤ r ≤ n, 1 ≤ k ≤ 2).
Output
对于每次询问回答一个整数占一行表示答案。
Example
Input4Output
6
1 2 1
3 4 1
2 3 2
1 3 2
2 4 1
1 4 2
2
0
2
3
1
4
题解:
因为线段树要开4倍空间。然而面对庞大的数据我们开maxn<<2的空间是肯定开不下的。
这时候就要用到动态开点线段树来节省空间了。( 或者离散化 )
动态开点也就是当用到那个节点的时候才给它分配空间,否则就不分配,就比如像这一道题n的大小是1e9,那么静态开点肯定炸空间了,,,但是你发现他询问的区间也就3e5个,可见用到的区间还是少数,所以每当用到一个区间我们再给他分配空间
代码:
1 /* 2 动态开点线段树 3 */ 4 #include<stdio.h> 5 #include<string.h> 6 #include<iostream> 7 #include<algorithm> 8 #include<queue> 9 #include<vector> 10 using namespace std; 11 const int maxn=3e5+10; 12 const int INF=0x3f3f3f3f; 13 typedef long long ll; 14 struct Node 15 { 16 int l,r,sum,lazy; 17 Node() 18 { 19 l=0,r=0,sum=0,lazy=0; 20 } 21 } node[maxn*50]; 22 int cnt=1; //开点的数量 23 void pushdown(int l,int r,int k) //k是父节点在数组中的序号 24 { 25 int mid=(l+r)>>1; 26 if(l!=r) 27 { 28 if(!node[k].l) node[k].l=++cnt; 29 if(!node[k].r) node[k].r=++cnt; 30 31 if(node[k].lazy==2) 32 { 33 node[node[k].l].sum=node[node[k].r].sum=0; 34 } 35 else 36 { 37 node[node[k].l].sum=mid-l+1; 38 node[node[k].r].sum=r-mid; 39 } 40 node[node[k].l].lazy=node[k].lazy; 41 node[node[k].r].lazy=node[k].lazy; 42 } 43 node[k].lazy=0; 44 } 45 //往线段树里面插入一个区间[L,R] 46 void Insert(int l,int r,int &k,int L,int R,int p) 47 { 48 if(!k) k=++cnt; //这个k也就相当于我们要对node[k]这个节点进行操作 49 //node[1]是根节点,因为我们这是动态开点,所以没有开点的节点都是初始值0 50 if(l>=L && r<=R) //如果满足这个条件也就不需要pushdown,因为我们不需要下面节点就可以得到[l,r]区间内的答案 51 { 52 if(p==2) node[k].sum=0; 53 else node[k].sum=r-l+1; 54 node[k].lazy=p; 55 return; 56 } 57 //如果不满足上面那个判断,那么我们就要递归进入k的左右子节点,这个时候,你要保证左右子点都已经被修改好了 58 //即,懒惰标记lazy是0 59 if(node[k].lazy) pushdown(l,r,k); 60 int mid=(l+r)>>1; 61 if (mid>=L) Insert(l,mid,node[k].l,L,R,p); 62 if (mid<R) Insert(mid+1,r,node[k].r,L,R,p); 63 node[k].sum=node[node[k].l].sum+node[node[k].r].sum; 64 } 65 int main() 66 { 67 //printf("%d %d\n",node[1].l,node[1].r); 68 int n,q; 69 scanf("%d %d",&n,&q); 70 int k=1; 71 for (int i=1; i<=q; i++) 72 { 73 int l,r,p; 74 scanf("%d %d %d",&l,&r,&p); 75 Insert(1,n,k,l,r,p); 76 printf("%d\n",n-node[1].sum); 77 } 78 return 0; 79 }