COCI 2017/2018 Round #2,November 4th,2017 F Plahte[线段树+set启发式合并]

题意:给你n个矩形和m个有颜色的点,保证不同矩形的边没有公共部分,但一个矩形可能会覆盖另一个矩形,求每个矩形的中的点的颜色的种类数。

题解:最重要的是矩形没有公共部分,我们定义0为包含所有矩形的矩形,所以这张图肯定是以0为根节点的树。然后我们通过遍历x通过线段树得出矩形的覆盖情况与点所属的最小矩形。然后遍历这颗树,通过set保存颜色,启发式合并得出答案。时间复杂度为O(n*logn+n*logn*logn)。

AC代码:

#include
#include
#include
#include
#include
#define N 80005
using namespace std;
struct node
{
	int x,low,high,op,id;
	node(){}
	node(int x,int low,int high,int op,int id)
	{
		this->x=x;
		this->low=low;
		this->high=high;
		this->op=op;
		this->id=id;
	} 
}p[N*3];
int b[N*3],top,tree[N*12],pre[N],ans[N],who[N];
setst[N];
set::iterator it;
vectorvt[N];
int tot=0;
bool cmp(node a,node b)
{
	if(a.x==b.x)return a.op>1;
	if(tree[root]!=-1)pushdown(root);
	if(r<=mid)update(l,r,L,mid,root<<1,k);
	else if(l>mid)update(l,r,mid+1,R,root<<1|1,k);
	else 
	{
		update(l,mid,L,mid,root<<1,k);
		update(mid+1,r,mid+1,R,root<<1|1,k);
	}
}
int query(int pos,int L,int R,int root)
{
	if(L==R)return tree[root];
	int mid=L+R>>1;
	if(tree[root]!=-1)pushdown(root);
	if(pos<=mid)return query(pos,L,mid,root<<1);
	else return query(pos,mid+1,R,root<<1|1);
}
int merge(int u,int v)
{
	if(st[u].size()


你可能感兴趣的:(线段树,启发式合并)