博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
树链剖分——线段树区间合并bzoj染色
阅读量:4632 次
发布时间:2019-06-09

本文共 2866 字,大约阅读时间需要 9 分钟。

线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了。。

一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些

struct Seg{    int lc,rc,tot;    Seg(){lc=rc=-1;tot=0;}};Seg seg[maxn<<2];int lazy[maxn<<2];Seg pushup(Seg a,Seg b){    if(!a.tot)return b;    if(!b.tot)return a;    Seg res;    res.lc=a.lc,res.rc=b.rc;    res.tot=a.tot+b.tot;    if(a.rc==b.lc)res.tot--;    return res;}

向上爬时更新操作不用变,但是询问操作需要改变

同样有一些值得注意的地方:向上爬的两条链是有顺序的,合并时顺序不能搞反,也不能像普通树链剖分那样直接swap

int Query(int x,int y){    Seg A,B;    while(top[x]!=top[y]){        if(d[top[x]]
id[y]) A=pushup(query(id[y],id[x],1,n,1),A); else B=pushup(query(id[x],id[y],1,n,1),B); if(A.lc==B.lc)return A.tot+B.tot-1; else return A.tot+B.tot;}

最后是完整代码

#include
using namespace std;#define maxn 100005struct Edge{
int to,nxt;}edge[maxn<<1];int c[maxn],head[maxn],tot,n;int f[maxn],son[maxn],d[maxn],size[maxn];int cnt,id[maxn],rk[maxn],top[maxn];void dfs1(int x,int pre,int deep){ size[x]=1,d[x]=deep; for(int i=head[x];i!=-1;i=edge[i].nxt){ int y=edge[i].to; if(y==pre)continue; f[y]=x;dfs1(y,x,deep+1);size[x]+=size[y]; if(size[son[x]]
>1; build(lson);build(rson); seg[rt]=pushup(seg[rt<<1],seg[rt<<1|1]);}void update(int L,int R,int c,int l,int r,int rt){ if(L<=l && R>=r){ lazy[rt]=c;seg[rt].lc=seg[rt].rc=c; seg[rt].tot=1;return; } pushdown(rt); int m=l+r>>1; if(L<=m)update(L,R,c,lson); if(R>m)update(L,R,c,rson); seg[rt]=pushup(seg[rt<<1],seg[rt<<1|1]);}Seg query(int L,int R,int l,int r,int rt){ if(L<=l && R>=r)return seg[rt]; pushdown(rt); int m=l+r>>1; Seg res; if(L<=m)res=pushup(res,query(L,R,lson)); if(R>m)res=pushup(res,query(L,R,rson)); return res;}void Update(int x,int y,int c){ while(top[x]!=top[y]){ if(d[top[x]]
id[y])swap(x,y); update(id[x],id[y],c,1,n,1);}int Query(int x,int y){ Seg A,B; while(top[x]!=top[y]){ if(d[top[x]]
id[y]) A=pushup(query(id[y],id[x],1,n,1),A); else B=pushup(query(id[x],id[y],1,n,1),B); if(A.lc==B.lc)return A.tot+B.tot-1; else return A.tot+B.tot;}void init(){ memset(head,-1,sizeof head); memset(lazy,-1,sizeof lazy); tot=0;}void addedge(int u,int v){ edge[tot].to=v;edge[tot].nxt=head[u];head[u]=tot++;}int main(){ init();int q; cin>>n>>q; for(int i=1;i<=n;i++)cin>>c[i]; for(int i=1;i
>x>>y; addedge(x,y);addedge(y,x); } cnt=0;dfs1(1,0,1),dfs2(1,1); build(1,n,1); char op[2];int x,y,z; while(q--){ scanf("%s",op); if(op[0]=='Q'){scanf("%d%d",&x,&y); cout<
<<'\n';} if(op[0]=='C'){scanf("%d%d%d",&x,&y,&z);Update(x,y,z);} } }
View Code

 

转载于:https://www.cnblogs.com/zsben991126/p/10759166.html

你可能感兴趣的文章
解释一下python中的关系运算符
查看>>
【模板】组合数学
查看>>
data,bdata,idata,pdata,xdata,code存储类型与存储区
查看>>
JS知识整理之 Call&Apply方法
查看>>
MySql 和 PostGres 对照表
查看>>
sqlmap使用
查看>>
路由转发
查看>>
UITableView
查看>>
MySQL笔记
查看>>
SQL查询强化训练(2)
查看>>
Django 分页
查看>>
layuiAdmin 项目修改
查看>>
创新点子:博客图文混编工具
查看>>
NSUserDefault、NSMutableDictionary的setValue和setObject区别
查看>>
TreeSet&第三方比较器&Map
查看>>
经典算法mark
查看>>
http://channel9.msdn.com/Events/MIX
查看>>
静态页面:html5个人博客模板《绅士》
查看>>
mvc 基础概念
查看>>
mysql数据恢复
查看>>