Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

蒟蒻的ckw染色树的做法

Posted by qdnoip at 2016-12-11 14:29:40 on Problem 2528
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 &lt=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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator