传送门:点击打开链接
题目大意:
给定一个 1 ~ 10000000 的区间,然后有N次操作(N <= 10000),第i次操作是将 l~r 区间覆盖为i。问最后一共有多少种有颜色。
解题思路:
一开始想到了离散化,但是想了一想感觉有点麻烦 然后就问专职搞数据结构的队友。然后他说了 动态线段树。思路如下:
定义一个ID。然后 根节点1表示掌管1-MAXN颜色的区间。然后每次都是动态的建树。当一个区间的左子区间还不存在时。建立它,并且记录下每个区间的左子区间和右子区间的ID.那么就可以搞了。
最后再用一个DFS 用SET来记录一共出现了多少种颜色。
注意:
当将一个区间的左子区间和右子区间被它更新之后时,一定要把他清零。
还有那个maxn。开始是未知的。
#include <set>
#include <cstdio>
using namespace std;
#define maxn 2000000
int lson[maxn],rson[maxn],color[maxn];
int cnt,root;
void build()
{
cnt = 2;
root = 1;
lson[root] = 0;
rson[root] = 0;
color[root] = 0;
}
void pushdown(int id)
{
if(!lson[id])
{
lson[id] = cnt++;
lson[lson[id]] = 0;
rson[lson[id]] = 0;
color[lson[id]] = 0;
}
if(!rson[id])
{
rson[id] = cnt++;
lson[rson[id]] = 0;
rson[rson[id]] = 0;
color[rson[id]] = 0;
}
if(color[id])
{
color[lson[id]] = color[id];
color[rson[id]] = color[id];
color[id] = 0;
}
}
void op(int id,int ls,int rs,int l,int r,int c)
{
if(ls >= l && rs <= r)
{
color[id] = c;
return;
}
pushdown(id);
int mid = (ls+rs)>>1;
if(l <= mid) op(lson[id],ls,mid,l,r,c);
if(mid < r) op(rson[id],mid+1,rs,l,r,c);
}
set<int > ans;
void dfs(int id)
{
if(color[id])
{
ans.insert(color[id]);
return;
}
if(lson[id]) dfs(lson[id]);
if(rson[id]) dfs(rson[id]);
}
int main()
{
int T;
scanf("%d",&T);
for(int ks = 1;ks <= T;ks++)
{
int n;
scanf("%d",&n);
ans.clear();
build();
for(int i = 1;i <= n;i++)
{
int l,r;
scanf("%d %d",&l,&r);
op(root,1,10000000,l,r,i);
}
dfs(root);
printf("%d\n",ans.size());
}
return 0;
}