bzoj2243树链剖分+染色段数
终于做了一道不是一眼出思路的代码题(⊙o⊙)
之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱)
实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开线段树的时候记录一下就好了
事实上我开了一个node,并且写了一个mix还是大大减小了代码量(对于我这种手残党来说同时大大减小了错误率)
由于前几题做的都是树链剖分,并没有在这一方面出问题,然而线段树还是不熟练,刚写完的时候居然忘记down了(mdzz)
对wa了N遍的总结:
由于是树上两个点间的路径,既有向上的路也有向下的路,然而树剖下来的结果是按深度排的,所以在链上跑的时候会发现一段链的左右(l和r)有时候是相反的,在合并几条链的时候一定要注意(事实证明我这么多遍wa全是因为没有翻转链)
对这一类问题的总结:
对于每一段都考虑有用(会对周围产生影响)的信息,在染色段数中就是两端(因为可能和隔壁合并)
//加了一大堆斜杠的是第一遍写之后补的
#include <cstdio>
#include <iostream>
#define mid (l+r)/2
using namespace std;
int m=,N=,n,M,p,q,o;
int to[],nex[],fir[],son[],bro[],co[];
int size[],l[],pos[],fa[],h[],top[];
struct node{int s,l,r;bool b;}t[],ans[];
inline void add(int x,int y){to[++m]=y;nex[m]=fir[x];fir[x]=m;}
inline node mix(node x,node y){return (node){x.s+y.s-(x.r==y.l),x.l,y.r,};}
int build(int now,int fat)
{
size[now]=;fa[now]=fat;h[now]=h[fat]+;
for(int i=fir[now];i;i=nex[i])
if(to[i]!=fat)
size[now]+=build(to[i],now),bro[to[i]]=son[now],son[now]=to[i];
return size[now];
}
void pou(int now,int to)
{
l[++N]=now;pos[now]=N;top[now]=to;
int max=son[now];
if(!max) return;
for(int i=bro[max];i;i=bro[i])
if(size[i]>size[max]) max=i;
pou(max,to);
for(int i=son[now];i;i=bro[i])
if(i!=max) pou(i,i);
}
void down(int now)////////////////////////////
{
if(t[now].b)
{
t[now].b=;t[now*].b=t[now*+].b=;
t[now*].s=t[now*+].s=;
t[now*].l=t[now*].r=t[now*+].l=t[now*+].r=t[now].l;
}
}
void work(int now,int l,int r,int x,int y,int z)
{
if(l==x && r==y)
{ t[now]=(node){,z,z,}; return;}
down(now);
if(x<=mid)
work(now*,l,mid,x,min(y,mid),z);
if(y>mid)
work(now*+,mid+,r,max(x,mid+),y,z);
t[now]=mix(t[now*],t[now*+]);
}
node que(int now,int l,int r,int x,int y)
{
if(l==x && r==y)
return t[now];
down(now);
if(y<=mid) return que(now*,l,mid,x,y);
if(x>mid) return que(now*+,mid+,r,x,y);
return mix(que(now*,l,mid,x,mid),que(now*+,mid+,r,mid+,y));
}
void solve(int x,int y,int z)
{
bool b=;ans[]=ans[]=(node){,-,-,};
while(top[x]!=top[y])
{
if(h[top[x]]<h[top[y]]) swap(x,y),b=!b;
if(z==-)
{
node tem=que(,,n,pos[top[x]],pos[x]);
if(!b) swap(tem.l,tem.r);///////////////////////////////
if(ans[b].s==) ans[b]=tem;
else
ans[b]=b?mix(tem,ans[b]):mix(ans[b],tem);
}
else
work(,,n,pos[top[x]],pos[x],z);
x=fa[top[x]];
}
if(h[x]>h[y]) swap(x,y),b=!b;//////////////////
if(z==-)
{
node tem=que(,,n,pos[x],pos[y]);b=!b;////////////////
if(!b) swap(tem.l,tem.r);
if(ans[b].s==) ans[b]=tem;
else
ans[b]=b?mix(tem,ans[b]):mix(ans[b],tem);
printf("%d\n",mix(ans[],ans[]).s);
}
else
work(,,n,pos[x],pos[y],z);
}
int main()
{
scanf("%d%d",&n,&M);
for(int i=;i<=n;i++)
scanf("%d",&co[i]);
for(int i=;i<n;i++)
scanf("%d%d",&p,&q),add(p,q),add(q,p);
build(,);
pou(,);
for(int i=;i<=n;i++)
work(,,n,pos[i],pos[i],co[i]);
for(int i=;i<=M;i++)
{
char ch=getchar();
while(ch!='C' && ch!='Q') ch=getchar();
if(ch=='C')
scanf("%d%d%d",&p,&q,&o),solve(p,q,o);
else
scanf("%d%d",&p,&q),solve(p,q,-);
}
return ;
}
bzoj2243树链剖分+染色段数的更多相关文章
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- bzoj2243 树链剖分
https://www.lydsy.com/JudgeOnline/problem.php?id=2243 新学的树剖,在维护的时候线段树维护区间内颜色数量以及左右两端的颜色.统计的时候区间合并时判断 ...
- bzoj2243树链剖分+区间合并
树链上区间合并的问题比区间修改要复杂,因为每一条重链在线段树上分布一般都是不连续的,所以在进行链上操作时要手动将其合并起来,维护两个端点值 处理时的方向问题:lca->u是一个方向,lca-&g ...
- [SDOI2011]染色 BZOJ2243 树链剖分+线段树
分析: 区间合并,lcol是左端点的颜色编号,rcol是右端点的颜色编号,那么我们向上合并的时候,如果左儿子的rcol等于右儿子的lcol那么区间的sum--. 另外,如果重链顶的颜色等于重链顶的父节 ...
- hdu3966 树链剖分+成段更新
给你n个点,m条边,p次操作.n个点相连后是一棵树.每次操作可以是x 到 y 增加 z,或者减z,或者问当前点的值是多少. 可以将树分成链,每个点在线段树上都有自己的点,然后线段树成段更新一下. #p ...
- BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)
题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...
- HDU3966-Aragorn's Story(树链剖分)
第一道树链剖分. 早就想学..一直懒.. 感觉还是比较简单的. 主要是要套其他数据结构,线段树大概还好,平衡树之类的肯定就跪了. http://blog.csdn.net/acdreamers/art ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...
随机推荐
- MySQL 查询所有子级函数
BEGIN DECLARE sChildList VARCHAR(4000); DECLARE sChildTemp VARCHAR(4000); SET sChildTemp =cast(rootI ...
- Android Duplicate files copied in APK
今天调试 Android 应用遇到这么个问题: Duplicate files copied in APK META-INF/DEPENDENCIES File 1: httpmime-4.3.2.j ...
- Docker知识-1
[编者的话]本文用图文并茂的方式介绍了容器.镜像的区别和Docker每个命令后面的技术细节,能够很好的帮助读者深入理解Docker. 这篇文章希望能够帮助读者深入理解Docker的命令,还有容器(co ...
- 在Ubuntu 14.04安装和使用Docker
Docker是一个开源软件,它可以把一个Linux应用和它所依赖的一切(比如配置文件)都封装到一个容器.然而,Docker与虚拟机不同,它使用了沙箱机制,Docker容器不运行操作系统,它共享主机上的 ...
- LL(1)文法
<源程序>→<外部声明>|<外部声明><函数体> <外部申明>→<头文件><函数声明>|其他声明 <函数体&g ...
- Web Service 的创建简单编码、发布和部署
最近,老大准备将已有的C/S架构项目中的通信部分做成通用,需要将其支持WebService为以后项目向着B/S架构升级做好铺垫,为此身为屌丝的我去各种百度WebService是个什么卵玩意,然后逐渐搭 ...
- 使用PowerShell来修改文件访问,创建,修改时间属性
Function Set-FileTimeStamps { Param ( [Parameter(mandatory=$true)] [string[]]$path, [datetime]$date ...
- (转)Excel的 OleDb 连接串的格式(连接Excel 2003-2013)
string strCon = "Provider=Microsoft.ACE.OLEDB.12.0;data source=" + filePath + ";Exten ...
- css sprite,css雪碧图生成工具V3.0更新
V3.0主要改进 1.增加了单独添加单张图片以及删除单张图片的功能 2.增加了生成.sprite文件用以保存雪碧图信息 3.增加了打开.sprite文件功能 什么是css sprite CSS spr ...
- 远程debug调试java代码
远程debug调试java代码 日常环境和预发环境遇到问题时,可以用远程调试的方法本地打断点,在本地调试.生产环境由于网络隔离和系统稳定性考虑,不能进行远程代码调试. 整体过程是通过修改远程服务JAV ...