| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
蒟蒻的ckw染色树的做法ckw染色树就是ckw染色线段数的简称……
百度什么的可定搜不到……
其核心内容就是ltag,rtag和ctag
能处理的问题……这道题就是模板
还有会场预约(这个应该更模板)等,尽管有更好的算法
但是用ckw染色树基本上可以做到无脑套用,然后复杂度依然是nlgn(虽然通常来讲会常数大一点),可以水过很多题目……
当父节点的操作会影响到子节点的时候,我们显然需要记录子节点是否需要被修改(ltag,rtag)。通常这个修改就是撤销(delete_segment),最后需要的问题形如"有多少条线段还存活着",所以还需要O(q)的空间把询问操作记录下来。
ckw染色树可以做到在线询问。
对于这个题目的更新操作为例。
如果这个区间覆盖:
如果已经被染色,撤销当前的颜色。
对于这道题,记录一下当前颜色还剩下多少last。
query[ctag].last-=(right-left+1);
如果为0,就segment_cnt--,表示这条线段已经被全部删除掉了。
对于会场预约,直接把整条线段删除就好了(递归调用delete(整棵树的根节点,query[ctag].left,query[ctag].right),然后segment_cnt++)。
显然对于这道题目的delete操作是不需要再写一个函数的(因为不用递归),所以只有这个部分需要针对不同题目修改。
然后如果左子树有颜色(ltag==true),那么将左子树涂上颜色0(paint(rt->tc,0))并ltag=false。右子树同理。然后ctag=color;return;
如果这个区间没有被覆盖,
若和左子树区间有交集,递归涂色(paint(rt->rc,color))并ltag=1;
右子树同理。
然后说说会场预约的delete操作
没什么好说的,唯一一点,一个区间可能只是删除一部分,所以要返回一个值,表示这个区间及其子树是否没有颜色。
附上代码。一般ckw染色树的代码都很长……
//POJ2528
#include<cstdio>
#include<algorithm>
#include<vector>
#define MAXM 10000
using namespace std;
struct query{
int u,v,last;
}q[MAXM+10];
struct segment{
int ctag,ltag,rtag;
}seg[16*MAXM+10];
int segment_cnt=0;
vector<int> vec;
int init_segment(int rt,int lef,int rig)
{
seg[rt].ctag=seg[rt].ltag=seg[rt].rtag=0;
if(lef==rig) return 0;
int mid=(lef+rig)/2;
init_segment(rt*2,lef,mid);
init_segment(rt*2+1,mid+1,rig);
return 0;
}
int push_down(int rt,int lef,int rig)
{
int mid=(lef+rig)/2;
seg[rt*2].ctag=seg[rt].ctag;
seg[rt*2+1].ctag=seg[rt].ctag;
seg[rt].ctag=0;seg[rt].ltag=seg[rt].rtag=1;
return 0;
}
int insert_segment(int root,int lef,int rig,int s,int t,int color)
{
int <=seg[root].ltag;
int &rt=seg[root].rtag;
int &ct=seg[root].ctag;
int mid=(lef+rig)/2;
if(s<=lef&&rig<=t)
{
if(ct!=0)
{
q[ct].last-=rig-lef+1;
if(q[ct].last==0) segment_cnt--;
}
if(lt!=0) insert_segment(root*2,lef,mid,s,t,0);
if(rt!=0) insert_segment(root*2+1,mid+1,rig,s,t,0);
lt=rt=0;ct=color;
return 0;
}
if(ct) push_down(root,lef,rig);
if(s<=mid) insert_segment(root*2,lef,mid,s,t,color),lt=1;
if(mid<t) insert_segment(root*2+1,mid+1,rig,s,t,color),rt=1;
}
int getid(int x)
{
return lower_bound(vec.begin(),vec.end(),x)-vec.begin()+1;
}
int main()
{
int T,m,u,v;scanf("%d",&T);
while(T--)
{
scanf("%d",&m);
segment_cnt=m;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].u,&q[i].v);
vec.push_back(q[i].u);
vec.push_back(q[i].v);
}
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
int n=vec.size()+2;
init_segment(1,1,n);
for(int i=1;i<=m;i++)
{
int idu=getid(q[i].u),idv=getid(q[i].v);
q[i].last=idv-idu+1;
insert_segment(1,1,n,idu,idv,i);
}
printf("%d\n",segment_cnt);
}
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator