[SDOI2011]染色

题目描述

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

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

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

如“112221”由3段组成:“11”、“222”和“1”。

请你写一个程序依次完成这m个操作。

输入输出格式

输入格式

第一行包含2个整数n和m,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。

下面 行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

输出格式

对于每个询问操作,输出一行答案。

说明

数N<=105,操作数M<=105,所有的颜色C为整数且在[0, 10^9]之间。


本来想复习一下树剖的,谁知道这题打起来超恶心。。

线段树上维护一下区间左端点颜色和右端点颜色,多的减掉就行啦


Code:

#include <cstdio>
#define ls id<<1
#define rs id<<1|1
int min(int x,int y){return x<y?x:y;}
int max(int x,int y){return x>y?x:y;}
const int N=2e5+10;
int head[N],to[N],Next[N],cnt;
void add(int u,int v)
{
to[++cnt]=v;Next[cnt]=head[u];head[u]=cnt;
}
int top[N],dep[N],siz[N],f[N],dfn[N],ws[N],ha[N],dfs_clock,n,m;
void dfs1(int now)
{
++siz[now];
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(f[now]!=v)
{
dep[v]=dep[now]+1;
f[v]=now;
dfs1(v);
siz[now]+=siz[v];
if(siz[ws[now]]<siz[v])
ws[now]=v;
}
}
}
void dfs2(int now,int anc)
{
dfn[now]=++dfs_clock;
ha[dfs_clock]=now;
top[now]=anc;
if(ws[now]) dfs2(ws[now],anc);
for(int i=head[now];i;i=Next[i])
if(!dfn[to[i]])
dfs2(to[i],to[i]);
}
int clo[N],lc[N<<2],rc[N<<2],sum[N<<2],lazy[N<<2];
void updata(int id)//保证不为叶子
{
sum[id]=sum[ls]+sum[rs]-(rc[ls]==lc[rs]);
lc[id]=lc[ls];
rc[id]=rc[rs];
}
void build(int id,int l,int r)
{
if(l==r)
{
lc[id]=rc[id]=clo[ha[l]];
sum[id]=1;
return;
}
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
updata(id);
}
void pushdown(int id)//保证不为叶子
{
if(lazy[id])
{
lazy[ls]=lazy[rs]=lc[ls]=lc[rs]=rc[ls]=rc[rs]=lazy[id];
sum[ls]=sum[rs]=1;
lazy[id]=0;
}
}
int line=0;
void change(int id,int l,int r,int L,int R,int color)
{
if(L!=R) pushdown(id);
if(l==L&&r==R)
{
lazy[id]=lc[id]=rc[id]=color;
sum[id]=1;
return;
}
int Mid=L+R>>1;
if(r<=Mid) change(ls,l,r,L,Mid,color);
else if(l>Mid) change(rs,l,r,Mid+1,R,color);
else change(ls,l,Mid,L,Mid,color),change(rs,Mid+1,r,Mid+1,R,color);
updata(id);
}
int query(int id,int l,int r,int L,int R,int &cl,int &cr)
{
if(L!=R) pushdown(id);
if(l==L&&r==R)
{
cl=lc[id],cr=rc[id];
return sum[id];
}
int Mid=L+R>>1,c0,c1;
if(r<=Mid) return query(ls,l,r,L,Mid,cl,cr);
else if(l>Mid) return query(rs,l,r,Mid+1,R,cl,cr);
else return query(ls,l,Mid,L,Mid,cl,c0)+query(rs,Mid+1,r,Mid+1,R,c1,cr)-(rc[ls]==lc[rs]);
}
void t_change(int x,int y,int c)
{
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
change(1,dfn[top[x]],dfn[x],1,n,c);
x=f[top[x]];
}
else
{
change(1,dfn[top[y]],dfn[y],1,n,c);
y=f[top[y]];
}
}
change(1,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]),1,n,c);
}
int t_query(int x,int y)
{
int s=0,xc=0,yc=0,cl,cr;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
s+=query(1,dfn[top[x]],dfn[x],1,n,cl,cr);
s-=cr==xc;
xc=cl;
x=f[top[x]];
}
else
{
s+=query(1,dfn[top[y]],dfn[y],1,n,cl,cr);
s-=cr==yc;
yc=cl;
y=f[top[y]];
}
}
s+=query(1,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]),1,n,cl,cr);
if(dfn[x]<dfn[y]) s-=(cl==xc)+(cr==yc);
else s-=(cl==yc)+(cr==xc);
return s;
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",clo+i);
for(int u,v,i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
dfs1(1),dfs2(1,1);
build(1,1,n);
char op[21];
for(int a,b,c,i=1;i<=m;i++)
{
scanf("%s%d%d",op,&a,&b);
if(op[0]=='C') scanf("%d",&c),t_change(a,b,c);
else printf("%d\n",t_query(a,b));
}
return 0;
}

2018.8.27

洛谷 P2486 [SDOI2011]染色/bzoj 2243: [SDOI2011]染色 解题报告的更多相关文章

  1. 洛谷 P1291 [SHOI2002]百事世界杯之旅 解题报告

    P1291 [SHOI2002]百事世界杯之旅 题目描述 "--在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字.只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽 ...

  2. 洛谷 P4714 「数学」约数个数和 解题报告

    P4714 「数学」约数个数和 题意(假):每个数向自己的约数连边,给出\(n,k(\le 10^{18})\),询问\(n\)的约数形成的图中以\(n\)为起点长为\(k\)的链有多少条(注意每个点 ...

  3. 洛谷 P4345 [SHOI2015]超能粒子炮·改 解题报告

    P4345 [SHOI2015]超能粒子炮·改 题意 求\(\sum_{i=0}^k\binom{n}{i}\),\(T\)组数据 范围 \(T\le 10^5,n,j\le 10^{18}\) 设\ ...

  4. 洛谷 P1691 有重复元素的排列问题 解题报告

    P1691 有重复元素的排列问题 题目描述 设\(R={r_1,r_2,--,r_n}\)是要进行排列的\(n\)个元素.其中元素\(r_1,r_2,--,r_n\)可能相同.使设计一个算法,列出\( ...

  5. 洛谷 P2746 [USACO5.3]校园网Network of Schools 解题报告

    P2746 [USACO5.3]校园网Network of Schools 题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作"接受学校&q ...

  6. 洛谷 P1121 环状最大两段子段和 解题报告

    P1121 环状最大两段子段和 题目描述 给出一段环状序列,即认为\(A_1\)和\(A_N\)是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 第一行是一个正整数 ...

  7. 洛谷 P1120 小木棍 [数据加强版]解题报告

    P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...

  8. 洛谷 P2336 [SCOI2012]喵星球上的点名 解题报告

    P2336 [SCOI2012]喵星球上的点名 题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 \(N\) 个喵星人,每个喵星人的 ...

  9. 洛谷 P2862 [USACO06JAN]把牛Corral the Cows 解题报告

    P2862 [USACO06JAN]把牛Corral the Cows 题目描述 Farmer John wishes to build a corral for his cows. Being fi ...

随机推荐

  1. Angular : 绑定, 参数传递, 路由

    如何把jquery导入angular npm install jquery --savenpm install @type/jquery --save-dev "node_modules/z ...

  2. Yaf学习(二)----Yaf初体验

    1.hello world 1.1 用yaf输出hello world 1.首先配置host,nginx 2.host不用多说,指向虚拟机IP即可 1.2 重点说一下nginx (只说server块) ...

  3. python面向对象-cs游戏示例

    #!/usr/local/bin/python3 # -*- coding:utf-8 -*- class Role(object): n = 123 # 类变量 name = "我是类na ...

  4. python并发编程之多进程、多线程、异步、协程、通信队列Queue和池Pool的实现和应用

    什么是多任务? 简单地说,就是操作系统可以同时运行多个任务.实现多任务有多种方式,线程.进程.协程. 并行和并发的区别? 并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任 ...

  5. JavaScript之原型 Prototype

    1.我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype.这个属性对应着一个对象,这个对象就是我们所谓的原型对象.如果函索作为普通函数调用prototype没有任何作用. 当函数以 ...

  6. POJ2553 汇点个数(强连通分量

    The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12070   Accepted: ...

  7. linux安装软件的几种方式(kali平台)和一些实用的软件(持续更新)

    安装软件前我们先更改镜像源,编辑 /etc/apt/sources.list 文件, 在文件最前面添加以下条目: #中科大更新源 deb https://mirrors.ustc.edu.cn/kal ...

  8. C++11中initializer lists的使用

    Before C++11,there was no easy way to do things like initialize a std::vector or std::map(or a custo ...

  9. Datetime与Datetime2的区别

    Datetime:        时间格式,对应于数据库中的DateTime类型,对应于.NET里面的System. DateTime类型.DateTime支持日期从1753年1月1日到9999年12 ...

  10. C#获取网络图片

    简单获取图片 string url = zhi_txt.Text;//图片地址 string dizhi = lujing.Text;//图片下载后保存路径及图片名称要写在一块 WebClient w ...