染色[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)路径上的颜色段数量。
输出
对于每个询问操作,输出一行答案。
样例输入
6 5 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
样例输出
3 1 2
提示
N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
题解
从开始打就感觉这题绝对会白打,果然如此。刚开始学树剖,对题型的了解还很不全面。
1.刚开始接触的 A难存的情缘 和 C货车运输 是边权下放、边权修改、路径查询
if(id[x]<id[y])
res=qd(res,query(id[x]+1,id[y],1,1,n));
void change(int p,int t,int r,int z,int y)
{
if(z==y)
{
mx[r]=t;
return;
}
int mid=(z+y)/2;
if(p<=mid) change(p,t,r*2,z,mid);
else change(p,t,r*2+1,mid+1,y);
mx[r]=qd(mx[r*2],mx[r*2+1]);
}
2.后来做的 B树上操作 和 E 树的统计 是点权修改、子树修改、路径查询,用到延迟标记和dfs序
if(id[x]<=id[y]) res+=query(id[x],id[y],1,1,n);
void change(int fr,int to,ll a,int r,int z,int y)
{
if(fr<=z&&to>=y)
{
lazy[r]+=a;
t[r].sm+=(long long)(y-z+1)*a;
return;
}
pushdown(r);
int mi=(t[r].le+t[r].ri)>>1;
if(fr<=mi) change(fr,to,a,r<<1,z,mi);
if(to>mi) change(fr,to,a,(r<<1)|1,mi+1,y);
pushup(r);
}
3.一直到今天的考试,我才明白change函数也可以像query一样分层操作。路径修改,路径查询,并且加了方向与合并。特别的是,把链上翻时比较链端和链端的父亲,来确认是否能合并一个色段。
query(id[fa[fx]],id[fa[fx]],1,1,n);
zd2=zd1;
query(id[fx],id[fx],1,1,n);
if(zd1==zd2) res--;
因为有hotel的经验,在线段树里记录左右端颜色并不难想到,延迟标记也是理所当然。其他步骤都比较容易,只有没打过的路径修改和查询合并是问题所在。只要fx和fa[fx]颜色相同,就可以合并一个色块。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int sj=;
int n,m,ys[sj],h[sj],e,a1,a2,a3,zd1,zd2;
char ss;
struct B
{
int u,v,ne;
}b[sj*];
void add(int x,int y)
{
e++;
b[e].ne=h[x];
b[e].u=x;
b[e].v=y;
h[x]=e;
}
void init()
{
scanf("%d%d",&n,&m);
memset(h,-,sizeof(h));
for(int i=;i<=n;i++)
scanf("%d",&ys[i]);
for(int i=;i<n;i++)
{
scanf("%d%d",&a1,&a2);
add(a1,a2);
add(a2,a1);
}
}
int fa[sj]={},son[sj]={},size[sj],dep[sj]={};
void dfs1(int x)
{
size[x]=;
for(int i=h[x];i!=-;i=b[i].ne)
{
int to=b[i].v;
if(to!=fa[x])
{
fa[to]=x;
dep[to]=dep[x]+;
dfs1(to);
size[x]+=size[to];
if(size[to]>size[son[x]]) son[x]=to;
}
}
}
int top[sj],pos[sj],id[sj],cnt,sd[sj];
void dfs2(int x,int y)
{
top[x]=y;
id[x]=++cnt;
sd[id[x]]=x;
pos[cnt]=x;
if(son[x]) dfs2(son[x],y);
for(int i=h[x];i!=-;i=b[i].ne)
{
int to=b[i].v;
if(to!=fa[x]&&to!=son[x])
dfs2(to,to);
}
}
struct Tree
{
int ds,zj,yj,zs,ys;
}t[sj*];
int lazy[sj*];
void build(int x,int z,int y)
{
t[x].zj=z;
t[x].yj=y;
if(z==y)
{
t[x].ds=;
t[x].zs=t[x].ys=ys[pos[z]];
return;
}
int mid=(z+y)>>,ze=x<<,ye=(x<<)|;
build(ze,z,mid);
build(ye,mid+,y);
t[x].ds=t[ze].ds+t[ye].ds;
if(t[ze].ys==t[ye].zs)
t[x].ds--;
t[x].ys=t[ye].ys;
t[x].zs=t[ze].zs;
}
void jh(int &x,int &y)
{
int jy=y;
y=x;
x=jy;
}
void pushdown(int x)
{
if(lazy[x]!=-)
{
int ze=x<<,ye=(x<<)|;
lazy[ze]=lazy[ye]=lazy[x];
t[ze].ds=t[ye].ds=;
t[ze].zs=t[ze].ys=lazy[x];
t[ye].zs=t[ye].ys=lazy[x];
lazy[x]=-;
}
}
void pushup(int x)
{
int ze=x<<,ye=(x<<)|;
t[x].ds=t[ze].ds+t[ye].ds;
if(t[ze].ys==t[ye].zs)
t[x].ds--;
t[x].ys=t[ye].ys;
t[x].zs=t[ze].zs;
}
int query(int s,int to,int r,int z,int y)
{
if(s==z&&to==y)
{
zd1=t[r].zs;
return t[r].ds;
}
pushdown(r);
int mid=(z+y)>>;
int ze=r<<,ye=(r<<)|;
if(to<=mid) return query(s,to,ze,z,mid);
if(s>mid) return query(s,to,ye,mid+,y);
int res=query(s,mid,ze,z,mid)+query(mid+,to,ye,mid+,y);
if(t[ze].ys==t[ye].zs) res--;
return res;
}
int Q(int x,int y)
{
int res=,fx=top[x],fy=top[y];
while(fx^fy)
{
if(dep[fx]<dep[fy])
{
jh(x,y);
jh(fx,fy);
}
res+=query(id[fx],id[x],,,n);
query(id[fa[fx]],id[fa[fx]],,,n);
zd2=zd1;
query(id[fx],id[fx],,,n);
if(zd1==zd2) res--;
x=fa[fx];
fx=top[x];
}
if(dep[x]>dep[y]) jh(x,y);
if(id[x]<=id[y]) res+=query(id[x],id[y],,,n);
return res;
}
void c(int s,int to,int a,int r,int z,int y)
{
if(s==z&&to==y)
{
lazy[r]=a;
t[r].ds=;
t[r].ys=t[r].zs=a;
return;
}
pushdown(r);
int mid=(z+y)>>;
int ze=r<<,ye=(r<<)|;
if(to<=mid) c(s,to,a,ze,z,mid);
if(s>mid) c(s,to,a,ye,mid+,y);
if(to>mid&&s<=mid)
{
c(s,mid,a,ze,z,mid);
c(mid+,to,a,ye,mid+,y);
}
pushup(r);
}
void C(int x,int y,int a)
{
int fx=top[x],fy=top[y];
while(fx^fy)
{
if(dep[fx]<dep[fy])
{
jh(x,y);
jh(fx,fy);
}
c(id[fx],id[x],a,,,n);
x=fa[fx];
fx=top[x];
}
if(dep[x]>dep[y]) jh(x,y);
if(id[x]<=id[y]) c(id[x],id[y],a,,,n);
}
void cl()
{
for(int i=;i<=m;i++)
{
scanf("%s",&ss);
scanf("%d%d",&a1,&a2);
if(ss=='Q')
printf("%d\n",Q(a1,a2));
if(ss=='C')
{
scanf("%d",&a3);
C(a1,a2,a3);
}
}
}
int main()
{
//freopen("t3.txt","r",stdin);
init();
dfs1();
dfs2(,);
memset(lazy,-,sizeof(lazy));
build(,,n);
cl();
//while(1);
return ;
}
染色[SDOI2011]的更多相关文章
- BZOJ 2243: [SDOI2011]染色 [树链剖分]
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6651 Solved: 2432[Submit][Status ...
- bzoj-2243 2243: [SDOI2011]染色(树链剖分)
题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6267 Solved: 2291 Descript ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- bzoj2243:[SDOI2011]染色
链剖就可以了.一开始的想法错了.但也非常接近了.妈呀调的要死...然后把字体再缩小一号查错起来比较容易QAQ. #include<cstdio> #include<cstring&g ...
- bzoj 2243 [SDOI2011]染色(树链剖分,线段树)
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4637 Solved: 1726[Submit][Status ...
- Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5020 Solved: 1872[Submit][Status ...
- 2243: [SDOI2011]染色
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3113 Solved: 1204[Submit][Status ...
- bzoj 2243 [SDOI2011]染色(树链剖分+线段树合并)
[bzoj2243][SDOI2011]染色 2017年10月20日 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询 ...
- [SDOI2011]染色
[SDOI2011]染色 题目描述 输入输出格式 输出格式: 对于每个询问操作,输出一行答案. 解法 ps:这题本来是树剖的,但我用lct写的,以下是lct的写法,树剖会有所不同 我们考虑把不同色点的 ...
随机推荐
- Linux: 安装NVIDIA显卡驱动
Linux(Fedora25, 64bit)台式机配备了NVIDIA显卡GTX950,但是仅仅使用开源驱动nouveau,无法发挥NVIDIA显卡的性能,所以可以考虑使用官方提供的显卡驱动. # 先安 ...
- PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/event.so'
这是因为启动apche 的时候重复加载了php的动态库模块了, 将:/etc/php.d/ 目录下的event.ini中的内容注释掉或者将文件删除即可
- 【Android Developers Training】 106. 创建并检测地理围栏
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 52. 打印照片
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- USACO Ordered Fractions
首先看一下题目 Consider the set of all reduced fractions between 0 and 1 inclusive with denominators less t ...
- React 在服务端渲染的实现
原文地址:Server-Side React Rendering 原文作者:Roger Jin 译者:牧云云 React 在服务端渲染的实现 React是最受欢迎的客户端 JavaScript 框架, ...
- 15.vue使用element-ui的el-input监听不了回车事件
问题描述: 使用vue.js 2.0发现,el-input的绑定回车事件用不了 原因: el-input封了一层,直接@keyup.enter是用不了的 例如: <el-input type=& ...
- VB6之SendMessage模拟拖放事件
原文链接:http://hi.baidu.com/coo_boi/item/e1e0f5ab45bddbdd5af191df 网上找了个C++的翻一下,原文链接:http://www.cnblogs. ...
- python编程快速上手之第8章实践项目参考答案
第8章实践项目之疯狂填词 创建一个一个疯狂填词(Mad Libs),程序,它将读入文本文件,并让用户在该文本文件中出现 ADJECTIVE,NOUN,VERB等单词的地方,加上他们自己的文本. 首先准 ...
- God 1.1.1 多线程之内存可见性
共享变量在线程间的可见性 synchronize实现可见性 volatile实现可见性 指令重排序 as-if-serial语义 volatile使用注意事项 synchronized和volatil ...