题目链接
题意
初始
[
1
,
n
]
[1,n]
[1,n] 为
1
1
1,
1
1
1 表示你需要工作,然后
q
q
q 行操作。
每次操作可以将某个区间
1
1
1 变为
0
0
0,或者
0
0
0 变为
1
1
1,求每次操作后存在多少个
1
1
1
思路
线段树动态开点裸题,离线离散化应该也可以吧。
动态开点相比普通线段树,多维护每个节点的左右儿子,用到某个点才给他开辟空间。
所以区间修改肯定要lazy一下,否则和没开一样。
每次修改开的点大概就logn个
代码
#include <bits/stdc++.h>
using namespace std;
int id;
struct Node
{
int sum, l, r, lazy;
}t[300005*50];
int build()
{
++id;
t[id].l = t[id].r = t[id].sum = 0;
t[id].lazy = -1;
return id;
}
void pushdown(int rt, int l, int r)
{
if(t[rt].lazy == -1) return;
int mid = (l+r)>>1;
if(l != r)
{
if(t[rt].l == 0) t[rt].l = build();
if(t[rt].r == 0) t[rt].r = build();
t[t[rt].l].lazy = t[rt].lazy;
t[t[rt].r].lazy = t[rt].lazy;
t[t[rt].l].sum = (mid-l+1)*t[rt].lazy;
t[t[rt].r].sum = (r-mid)*t[rt].lazy;
}
t[rt].lazy = -1;
}
void updata(int rt, int l, int r, int ql, int qr, int num)
{
if(ql <= l && r <= qr)
{
t[rt].lazy = num;
t[rt].sum = (r-l+1)*num;
return;
}
pushdown(rt,l,r);
int mid = (l+r) >> 1;
if(ql <= mid)
{
if(t[rt].l == 0) t[rt].l = build();
updata(t[rt].l,l,mid,ql,qr,num);
}
if(qr > mid)
{
if(t[rt].r == 0) t[rt].r = build();
updata(t[rt].r,mid+1,r,ql,qr,num);
}
t[rt].sum = t[t[rt].l].sum+t[t[rt].r].sum;
}
int main()
{
int n, q;
scanf("%d%d",&n,&q);
id = 0;
build();
while(q--)
{
int x, y, z;
scanf("%d%d%d",&x,&y,&z);
if(z == 1) updata(1,1,n,x,y,1);
else updata(1,1,n,x,y,0);
printf("%d\n",n-t[1].sum);
}
return 0;
}