染色[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的写法,树剖会有所不同 我们考虑把不同色点的 ...
随机推荐
- DataTables warning (table id = 'DataTables_Table_0');错误解决办法!
这个错误是table表格引起的,我是将条件语句和<td>标签做了调整后,消除的,个人认为是数据缺失引起的.
- Lucence_Curd
设置Field的类型 new StringField 不分词(id,身份证号,电话...) new StoredField 不分词(链接) new TextField 分词(文本) new Fload ...
- centos yum 没有可用软件包 nginx。
新装的centos7中没有nginx的镜像源 因为nginx位于第三方的yum源里面,而不在centos官方yum源里面 解决方案: 安装epel: 去epel官网: http://fedorapro ...
- js调试模式控制台输出信息
js调试模式控制台输出信息.console.log
- hibernate in List查询条件 sum求和使用参考
@Override public Integer getSumZongShuByidList(List<String> idList){ Integer zongshu = 0; Stri ...
- [编织消息框架][netty源码分析]10 ByteBuf 与 ByteBuffer
因为jdk ByteBuffer使用起来很麻烦,所以netty研发出ByteBuf对象维护管理内存使用ByteBuf有几个概念需要知道1.向ByteBuf提取数据时readerIndex记录最后读取坐 ...
- Kotlin基本语法和使用
Kotlin 是一个基于 JVM 的新的编程语言,由 JetBrains 开发.与Java相比,Kotlin的语法更简洁.更具表达性,而且提供了更多的特性. Kotlin是使用Java开发者的思维被创 ...
- Spring事务管理注意小事项
在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例外(RunTimeExcep ...
- 简单svg动画实现
一.将svg嵌入到html中 svg是指可伸缩矢量图形,它使用XML格式定义图像.在html中可以使用<svg>标签直接嵌入svg代码,例如: <svg version=" ...
- win7-x64安装mysql5.7.11(官方zip版)
1.下载官方安装包(http://www.mysql.com/downloads/),此zip包是没有安装器的(*.msi),也没有辅助配置的自动程序. 2.解压zip包,将文件放入指定目录,如:D: ...