题目大意:

  给定一棵有n个节点的无根树和m个操作,操作有2类:

  1、将节点a到节点b路径上所有点都染成颜色c;

  2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段)

思路:

  树剖之后,维护其两端的颜色、答案和标记即可。

代码:

#include<cstdio>
#include<iostream>
#define N 100001
using namespace std;
int n,m,cnt,dfn,vis[N],head[N],to[N<<],next[N<<],deep[N],size[N],top[N],id[N],v[N],pa[N],lazy[N<<],lc[N<<],rc[N<<],sum[N<<]; void ins(int x,int y)
{
to[++cnt]=y,next[cnt]=head[x],head[x]=cnt;
} void dfs1(int x)
{
size[x]=vis[x]=;
for (int i=head[x];i;i=next[i])
if (!vis[to[i]])
{
deep[to[i]]=deep[x]+;
pa[to[i]]=x;
dfs1(to[i]);
size[x]+=size[to[i]];
}
} void dfs2(int x,int chain)
{
int k=,i;
id[x]=++dfn;
top[x]=chain;
for (i=head[x];i;i=next[i])
if (deep[to[i]]>deep[x] && size[to[i]]>size[k]) k=to[i];
if (!k) return;
dfs2(k,chain);
for (i=head[x];i;i=next[i])
if (deep[to[i]]>deep[x] && to[i]!=k) dfs2(to[i],to[i]);
} void build(int l,int r,int cur)
{
sum[cur]=,lazy[cur]=-;
if(l==r)return;
int mid=l+r>>;
build(l,mid,cur<<),build(mid+,r,cur<<|);
} void update(int k)
{
lc[k]=lc[k<<],rc[k]=rc[k<<|];
if (rc[k<<]^lc[k<<|]) sum[k]=sum[k<<]+sum[k<<|];
else sum[k]=sum[k<<]+sum[k<<|]-;
} void pushdown(int l,int r,int k)
{
int tmp=lazy[k]; lazy[k]=-;
if (tmp==- || l==r) return;
sum[k<<]=sum[k<<|]=;
lazy[k<<]=lazy[k<<|]=tmp;
lc[k<<]=rc[k<<]=tmp;
lc[k<<|]=rc[k<<|]=tmp;
} void change(int L,int R,int l,int r,int cur,int val)
{
if (l==L && r==R) { lc[cur]=rc[cur]=val; sum[cur]=; lazy[cur]=val; return; }
int mid=L+R>>; pushdown(L,R,cur);
if (r<=mid) change(L,mid,l,r,cur<<,val);
else if (l>mid) change(mid+,R,l,r,cur<<|,val);
else change(L,mid,l,mid,cur<<,val),change(mid+,R,mid+,r,cur<<|,val);
update(cur);
} int ask(int L,int R,int l,int r,int cur)
{
if (l==L && r==R) return sum[cur];
int mid=L+R>>; pushdown(L,R,cur);
if (r<=mid) return ask(L,mid,l,r,cur<<);
else if (l>mid) return ask(mid+,R,l,r,cur<<|);
else
{
int tmp=;
if (rc[cur<<]^lc[cur<<|]) tmp=;
return ask(L,mid,l,mid,cur<<)+ask(mid+,R,mid+,r,cur<<|)-tmp;
}
} int getc(int l,int r,int cur,int x)
{
if (l==r) return lc[cur];
int mid=l+r>>; pushdown(l,r,cur);
if (x<=mid) return getc(l,mid,cur<<,x);
else return getc(mid+,r,cur<<|,x);
} int solvesum(int x,int y)
{
int sum=;
for (;top[x]!=top[y];x=pa[top[x]])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
sum+=ask(,n,id[top[x]],id[x],);
if (getc(,n,,id[top[x]])==getc(,n,,id[pa[top[x]]])) sum--;
}
if (deep[x]>deep[y]) swap(x,y);
return sum+=ask(,n,id[x],id[y],);
} void solvechange(int x,int y,int val)
{
for (;top[x]!=top[y];x=pa[top[x]])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
change(,n,id[top[x]],id[x],,val);
}
if (deep[x]>deep[y]) swap(x,y);
change(,n,id[x],id[y],,val);
} int main()
{
int i,a,b,c;
scanf("%d%d",&n,&m);
for(i=;i<=n;i++)scanf("%d",&v[i]);
for(i=;i<n;i++) scanf("%d%d",&a,&b),ins(a,b),ins(b,a);
dfs1(),dfs2(,),build(,n,);
for(i=;i<=n;i++) change(,n,id[i],id[i],,v[i]);
for(i=;i<=m;i++)
{
char ch[];
scanf("%s",ch);
if(ch[]=='Q')
{
scanf("%d%d",&a,&b);
printf("%d\n",solvesum(a,b));
}
else
{
scanf("%d%d%d",&a,&b,&c);
solvechange(a,b,c);
}
}
return ;
}

[SDOI2011]染色 题解的更多相关文章

  1. BZOJ2243:[SDOI2011]染色——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2243 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点 ...

  2. 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树

    题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...

  3. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  4. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5020  Solved: 1872[Submit][Status ...

  5. 2243: [SDOI2011]染色

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 3113  Solved: 1204[Submit][Status ...

  6. bzoj 2243 [SDOI2011]染色(树链剖分+线段树合并)

    [bzoj2243][SDOI2011]染色 2017年10月20日 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询 ...

  7. [Luogu 2486] SDOI2011 染色

    [Luogu 2486] SDOI2011 染色 树剖水题,线段树维护. 详细题解不写了. 我只想说我写的线段树又变漂亮了qwq #include <algorithm> #include ...

  8. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  9. BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并

    2243: [SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数 ...

随机推荐

  1. MSMQ创建消息队列出现“工作组安装计算机不支持该操作”

    [sceislqzw]:你在创建公有队列,而你的机器不属于任何域.一般工作组安装的计算机只能创建私有队列. System.Messaging.MessageQueue QueueReceive = n ...

  2. Delphi操作XML简介

    参考:http://www.delphifans.com/InfoView/Article_850.html Delphi 7支持对XML文档的操作,可以通过 TXMLDocument类来实现对XML ...

  3. Shell编程基础教程4--控制流结构

    4.控制流结构    4.1.控制结构            4.2.if then else语句        格式: if 条件1 //如果条件1为真 then 命令1 //那么,执行命令1 el ...

  4. SSH入门简单搭建例子

    因为公司涉及项目使用SSH,为了解SSH搭建方式和运作原理,就自己搭建了一个. 采用尽量以最少的JAR包,搭建一个简单的struts2+spring+hibernate环境,希望像我这样的入门者都能理 ...

  5. [LeetCode] Search Insert Position

    Given a sorted array and a target value, return the index if the target is found. If not, return the ...

  6. Oracle buffer cache

    Buffer Cache buffer cache 结构图 HASH链 ORACLE使用HASH算法,把buffer cache中每个buffer的buffer header串联起来,组成多条hash ...

  7. 运用ASMIOSTAT脚本监控asm disk磁盘性能

    1,脚本作用: 类似于OS的iostat检查磁盘的I/O性能,ASMIOSTAT 脚本用来检查ASM磁盘的性能, 2,下载AMSIOSTAT脚本http://files.cnblogs.com/fil ...

  8. 关于WCF的一些注意事项

    1.服务代理,建立通道的方法,要注意及时关掉代理,因为服务设置有一个服务的最大连接数,超过这个连接数,则后面的连接将会等待,一直到超时,报错!! 2.在已有配置的基础上,利用代码更改终结点,如果重设了 ...

  9. hdu 4759 大数+找规律 ***

    题目意思很简单. 就是洗牌,抽出奇数和偶数,要么奇数放前面,要么偶数放前面. 总共2^N张牌. 需要问的是,给了A X B Y  问经过若干洗牌后,第A个位置是X,第B个位置是Y 是不是可能的. Ja ...

  10. [Oracle] 生产上表的列类型更新

    由于粗心,数据库脚本生成的时候错将一个类型NUMBER(5)的字段类型改为 VARCHAR2(5) 直接进行表修改会报错,因为数据已经存在,不能进行更新: ); 大体思路如下:       将要更改类 ...