BZOJ2243: [SDOI2011]染色(树链剖分/LCT)
Description
Input
Output
对于每个询问操作,输出一行答案。
Sample Input
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
Sample Output
1
2
解题思路:
1.树链剖分:
只修改链,不修改关系,树链剖分。
线段树维护树链剖分序。
时间复杂度O(nlogn2)
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lll spc<<1
#define rrr spc<<1|1
using std::min;
using std::max;
using std::swap;
struct trnt{
int lc;
int rc;
int lzt;
int val;
}tr[];
struct pnt{
int hd;
int col;
int mxs;
int ind;
int fa;
int tp;
int wgt;
int dp;
}p[];
struct ent{
int twd;
int lst;
}e[];
struct bag{
int cl;
int cr;
int vl;
bag friend operator + (bag a,bag b)
{
if(!a.cl)
a.cl=b.cl;
if(!b.cr)
b.cr=a.cr;
return (bag){a.cl,b.cr,(a.vl+b.vl-(a.cr==b.cl)<)?:(a.vl+b.vl-(a.cr==b.cl))};
}
};
int n,m;
int cnt;
int dfn;
char cmd[];
void ade(int f,int t)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
void pushup(int spc)
{
tr[spc].lc=tr[lll].lc;
tr[spc].rc=tr[rrr].rc;
tr[spc].val=tr[lll].val+tr[rrr].val-(tr[lll].rc==tr[rrr].lc);
return ;
}
void chg(int spc,int v)
{
tr[spc].val=;
tr[spc].lc=tr[spc].rc=v;
tr[spc].lzt=v;
return ;
}
void pushdown(int spc)
{
if(tr[spc].lzt)
{
chg(lll,tr[spc].lzt);
chg(rrr,tr[spc].lzt);
tr[spc].lzt=;
}
return ;
}
void build(int l,int r,int pos,int spc,int v)
{
if(l==r)
{
tr[spc].lc=tr[spc].rc=v;
tr[spc].val=;
tr[spc].lzt=;
return ;
}
int mid=(l+r)>>;
if(pos<=mid)
build(l,mid,pos,lll,v);
else
build(mid+,r,pos,rrr,v);
pushup(spc);
return ;
}
void Basic_dfs(int x,int f)
{
p[x].dp=p[f].dp+;
p[x].fa=f;
int maxs=-;
p[x].wgt=;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f)
continue;
Basic_dfs(to,x);
p[x].wgt+=p[to].wgt;
if(p[to].wgt>maxs)
{
maxs=p[to].wgt;
p[x].mxs=to;
}
}
return ;
}
void Build_dfs(int x,int tpl)
{
if(!x)
return ;
p[x].tp=tpl;
p[x].ind=++dfn;
build(,n,dfn,,p[x].col);
Build_dfs(p[x].mxs,tpl);
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].ind)
continue;
Build_dfs(to,to);
}
}
void update(int l,int r,int ll,int rr,int spc,int v)
{
if(ll>rr)
return ;
if(l>rr||ll>r)
return ;
pushdown(spc);
if(ll<=l&&r<=rr)
{
chg(spc,v);
return ;
}
int mid=(l+r)>>;
update(l,mid,ll,rr,lll,v);
update(mid+,r,ll,rr,rrr,v);
pushup(spc);
return ;
}
bag mk(int a,int b,int c)
{
return (bag){a,b,c};
}
bag ask(int l,int r,int ll,int rr,int spc)
{
if(l>rr||ll>r)
return mk(,,);
pushdown(spc);
if(ll<=l&&r<=rr)
return mk(tr[spc].lc,tr[spc].rc,tr[spc].val);
int mid=(l+r)>>;
return ask(l,mid,ll,rr,lll)+ask(mid+,r,ll,rr,rrr);
}
int lca(int x,int y)
{
while(p[x].tp!=p[y].tp)
{
if(p[p[x].tp].dp<p[p[y].tp].dp)
swap(x,y);
x=p[p[x].tp].fa;
}
if(p[x].dp>p[y].dp)
swap(x,y);
return x;
}
void rvs(bag &a)
{
swap(a.cl,a.cr);
return ;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&p[i].col);
for(int i=;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
ade(a,b);
ade(b,a);
}
Basic_dfs(,);
Build_dfs(,);
while(m--)
{
scanf("%s",cmd);
if(cmd[]=='C')
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int f=lca(a,b);
while(p[a].tp!=p[f].tp)
{
update(,dfn,p[p[a].tp].ind,p[a].ind,,c);
a=p[p[a].tp].fa;
}
update(,dfn,p[f].ind,p[a].ind,,c);
a=b;
while(p[a].tp!=p[f].tp)
{
update(,dfn,p[p[a].tp].ind,p[a].ind,,c);
a=p[p[a].tp].fa;
}
update(,dfn,p[f].ind,p[a].ind,,c);
}
if(cmd[]=='Q')
{
int a,b; scanf("%d%d",&a,&b);
int f=lca(a,b);
bag ans=(bag){,,};
while(p[a].tp!=p[f].tp)
{
ans=ask(,dfn,p[p[a].tp].ind,p[a].ind,)+ans;
a=p[p[a].tp].fa;
}
if(a!=f)
ans=ask(,dfn,p[f].ind+,p[a].ind,)+ans;
bag ams=(bag){,,};
a=b;
while(p[a].tp!=p[f].tp)
{
ams=ask(,dfn,p[p[a].tp].ind,p[a].ind,)+ams;
a=p[p[a].tp].fa;
}
if(a!=f)
ams=ask(,dfn,p[f].ind+,p[a].ind,)+ams;
ans=ask(,dfn,p[f].ind,p[f].ind,)+ans;
rvs(ans);
ans=ans+ams;
printf("%d\n",ans.vl);
}
}
return ;
}
2.LCT:
比较板子了。
每次维护左侧颜色和右侧颜色(注意特判0节点值)
反转时要反转左右颜色。
路径提取一下输出答案就好了。
时间复杂度O(nlogn)理论上比树剖快
但是:
蒟蒻的我:splay常数居然比logn大

代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lll tr[spc].ch[0]
#define rrr tr[spc].ch[1]
#define ls ch[0]
#define rs ch[1]
using std::swap;
struct trnt{
int ch[];
int fa;
int lzt;
int chg;
int sum;
int val;
int lc;
int rc;
int wgt;
bool anc;
}tr[];
int n,m;
char cmd[];
bool whc(int spc)
{
return tr[tr[spc].fa].rs==spc;
}
void pushup(int spc)
{
tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+;
tr[spc].sum=tr[lll].sum+tr[rrr].sum+-(tr[lll].rc==tr[spc].val)-(tr[rrr].lc==tr[spc].val);
tr[spc].lc=tr[lll].lc?tr[lll].lc:tr[spc].val;
tr[spc].rc=tr[rrr].rc?tr[rrr].rc:tr[spc].val;
return ;
}
void trr(int spc)
{
if(!spc)
return ;
swap(lll,rrr);
swap(tr[spc].lc,tr[spc].rc);
tr[spc].lzt^=;
return ;
}
void upd(int spc,int v)
{
if(!spc)
return ;
tr[spc].val=tr[spc].lc=tr[spc].rc=v;
tr[spc].sum=;
tr[spc].chg=v;
return ;
}
void pushdown(int spc)
{
if(tr[spc].lzt)
{
trr(lll);
trr(rrr);
tr[spc].lzt=;
}
if(tr[spc].chg)
{
upd(lll,tr[spc].chg);
upd(rrr,tr[spc].chg);
tr[spc].chg=;
}
return ;
}
void recal(int spc)
{
if(!tr[spc].anc)
recal(tr[spc].fa);
pushdown(spc);
return ;
}
void rotate(int spc)
{
int f=tr[spc].fa;
bool k=whc(spc);
tr[f].ch[k]=tr[spc].ch[!k];
tr[spc].ch[!k]=f;
if(tr[f].anc)
{
tr[spc].anc=;
tr[f].anc=;
}else
tr[tr[f].fa].ch[whc(f)]=spc;
tr[spc].fa=tr[f].fa;
tr[f].fa=spc;
tr[tr[f].ch[k]].fa=f;
pushup(f);
pushup(spc);
return ;
}
void splay(int spc)
{
recal(spc);
while(!tr[spc].anc)
{
int f=tr[spc].fa;
if(tr[f].anc)
{
rotate(spc);
return ;
}
if(whc(spc)^whc(f))
rotate(spc);
else
rotate(f);
rotate(spc);
}
return ;
}
void access(int spc)
{
int lst=;
while(spc)
{
splay(spc);
tr[rrr].anc=;
tr[lst].anc=;
rrr=lst;
pushup(spc);
lst=spc;
spc=tr[spc].fa;
}
return ;
}
void Mtr(int spc)
{
access(spc);
splay(spc);
trr(spc);
return ;
}
void split(int x,int y)
{
Mtr(x);
access(y);
splay(y);
return ;
}
void link(int x,int y)
{
Mtr(x);
tr[x].fa=y;
return;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
tr[i].anc=;
scanf("%d",&tr[i].val);
tr[i].lc=tr[i].rc=tr[i].val;
}
for(int i=;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
link(a,b);
}
while(m--)
{
scanf("%s",cmd);
if(cmd[]=='Q')
{
int a,b;
scanf("%d%d",&a,&b);
split(a,b);
printf("%d\n",tr[b].sum);
}else{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
split(a,b);
upd(b,c);
}
}
return ;
}
BZOJ2243: [SDOI2011]染色(树链剖分/LCT)的更多相关文章
- Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5020 Solved: 1872[Submit][Status ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
- BZOJ2243[SDOI2011]染色——树链剖分+线段树
题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221 ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- bzoj-2243 2243: [SDOI2011]染色(树链剖分)
题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6267 Solved: 2291 Descript ...
- BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...
- BZOJ 2243: [SDOI2011]染色 [树链剖分]
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6651 Solved: 2432[Submit][Status ...
- BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并
2243: [SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数 ...
- 2243: [SDOI2011]染色(树链剖分+线段树)
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 8400 Solved: 3150[Submit][Status ...
随机推荐
- iOS 一个ViewController上显示2个tableView的方法
1.在StoryBoard上创建2个tableView,并用autolayout约束. 2.在ViewController上拖进来. @property (weak, nonatomic) IBOut ...
- iOS开发 - 数据归档与恢复 NSKeyedArchiver
归档与恢复归档 归档,英文Archiver['ɑrkɪvə],这里指的是将OC的对象存储为一个文件或者网络上的一个数据块. 恢复归档.英文UnArchiver,指的是将一个来自文件或网络的归档数据块恢 ...
- java调用com组件将office文件转换成pdf
在非常多企业级应用中都涉及到将office图片转换成pdf进行保存或者公布的场景,由于pdf格式的文档方便进行加密和权限控制(类似于百度文库).总结起来眼下将office文件转换 成pdf的方法主要有 ...
- HDU 5375 Gray Code 动归
题意:给你一串不确定的二进制码,其对应的格雷码的每一位有对应的权值,问转换成的格雷码的能取到的最大权值是多少. 思路:没有思路,乱搞也AC #pragma comment(linker, " ...
- Docker -- 2 -- 利用docker部署网站和数据库
在Docker – 系统整洁之道 – 1中已经对Docker的一些命令和Docker镜像的使用及操作做了记录. 这次就利用docker进行一次真正的实例使用,使用docker搭建一个简单的答题系统,这 ...
- su su- sudo区别概述
在Linux的操作中经常会用到su 命令进行用户的切换和sudo命令获取root权限,su su- sudo三个命令经常弄混,下面简单的讲解下. 一.查看su的命令帮助信息: pipci@openSU ...
- 测试理论--web测试方法总结
一.输入框 1.字符型输入框: (1)字符型输入框:英文全角.英文半角.数字.空或者空格.特殊字符“~!@#¥%……&*?[]{}”特别要注意单引号和&符号.禁止直接输入特殊字符时,使 ...
- 【Henu ACM Round#18 A】 Multiplication Table
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 遍历i从1..n 看看x%i==0以及x/i<=n是否成立. [代码] #include <iostream> u ...
- 【Henu ACM Round #13 E】Spy Syndrome 2
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 对m个串建立一棵字典树. 然后对主串. 尝试从第一个位置开始.在字典树中尝试匹配 如果匹配到了位置i 就再从位置i+1开始尝试匹配 ...
- 【Linux探索之旅】第四部分第三课:文件传输,潇洒同步
内容简单介绍 .第四部分第三课:文件传输.潇洒同步 2.第四部分第四课:分析网络.隔离防火 文件传输.潇洒同步 这一课的内容相对简单,所以我们慢慢享用. 经过上一课的学习.我们已经知道怎样远程连接到其 ...