洛谷 P2486 [SDOI2011]染色/bzoj 2243: [SDOI2011]染色 解题报告
[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]染色 解题报告的更多相关文章
- 洛谷 P1291 [SHOI2002]百事世界杯之旅 解题报告
P1291 [SHOI2002]百事世界杯之旅 题目描述 "--在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字.只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽 ...
- 洛谷 P4714 「数学」约数个数和 解题报告
P4714 「数学」约数个数和 题意(假):每个数向自己的约数连边,给出\(n,k(\le 10^{18})\),询问\(n\)的约数形成的图中以\(n\)为起点长为\(k\)的链有多少条(注意每个点 ...
- 洛谷 P4345 [SHOI2015]超能粒子炮·改 解题报告
P4345 [SHOI2015]超能粒子炮·改 题意 求\(\sum_{i=0}^k\binom{n}{i}\),\(T\)组数据 范围 \(T\le 10^5,n,j\le 10^{18}\) 设\ ...
- 洛谷 P1691 有重复元素的排列问题 解题报告
P1691 有重复元素的排列问题 题目描述 设\(R={r_1,r_2,--,r_n}\)是要进行排列的\(n\)个元素.其中元素\(r_1,r_2,--,r_n\)可能相同.使设计一个算法,列出\( ...
- 洛谷 P2746 [USACO5.3]校园网Network of Schools 解题报告
P2746 [USACO5.3]校园网Network of Schools 题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作"接受学校&q ...
- 洛谷 P1121 环状最大两段子段和 解题报告
P1121 环状最大两段子段和 题目描述 给出一段环状序列,即认为\(A_1\)和\(A_N\)是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 第一行是一个正整数 ...
- 洛谷 P1120 小木棍 [数据加强版]解题报告
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
- 洛谷 P2336 [SCOI2012]喵星球上的点名 解题报告
P2336 [SCOI2012]喵星球上的点名 题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 \(N\) 个喵星人,每个喵星人的 ...
- 洛谷 P2862 [USACO06JAN]把牛Corral the Cows 解题报告
P2862 [USACO06JAN]把牛Corral the Cows 题目描述 Farmer John wishes to build a corral for his cows. Being fi ...
随机推荐
- Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO
你有碰上过这样的提示吗? Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in t ...
- web视频播放
webm.mp4/h264 video.js hevc libde265.js hls/m3u8 hls.js
- java web相对路径和绝对路径总结
java web 开发过程中很多地方涉及url路径的问题,比如jsp页面.servlet之间的跳转.其实,可以将url中的/xxx看成一级目录,然后像看待目录层级之间的关系那样去看待url路径.接下来 ...
- 通过transpose和flip实现图像旋转90/180/270度
在fbc_cv库中,提供了对图像进行任意角度旋转的函数rotate,其实内部也是调用了仿射变换函数warpAffine.如果图像仅是进行90度倍数的旋转,是没有必要用warpAffine函数的.这里通 ...
- PowerPC为什么会没落,我自己的反思学习总结
PowerPC为什么会没落? Intel通过酷睿,拉大优势,使得苹果抛弃PowerPC PowerPC当年异常强大,曾经是Xbox的处理器,是Mac的处理器,占据了服务器的半壁江山:当时刚刚接触C ...
- 安装Sql Server 2008时出错
在安装Sql Server 2008的时候,出现一个错误,说是"SQL Server 2005 Express tools"安装了,需要移除,但是我在控制面板里面找了 ...
- 在阿里云上遇见更好的Oracle(四)
2016.5.13,北京,第七届数据库技术大会. 从最初的itpub社区,到后来被it168收购,DBA社区的线下聚会发展成2010年第一届数据库技术大会(DTCC).第一届大会汇聚了社区内活跃的各位 ...
- 官方文档 恢复备份指南五 Configuring the RMAN Environment
本章内容: Configuring the Environment for RMAN Backups 配置RMAN环境 Configuring RMAN to Make Backups to a ...
- BZOJ 3925 ZJOI2015 地震后的幻想乡 状压dp+期望
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3925 题意概述: 给出一张N点M边的最小生成树,其中每条边的长度为[0,1]的实数,求最小 ...
- poj1200 字符串hash 滚动哈希初探
假如要判断字符串A“AABA”是否是字符串B“AABAACAADAABAABA”的子串 最朴素的算法是枚举B的所有长度为4的子串,然后逐个与A进行对比,这样的时间复杂度是O(mn),m为A的长度,n为 ...