欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ2243

题目传送门 - 洛谷2486


题意概括

  一棵树,共n个节点。

  让你支持以下两种操作,共m次操作:

  1. 区间染色:给定两个节点,让你给树中链接这两个节点的路径染色。

  2. 区间询问:给定两个节点,让你求出连接这两个节点的路径的色段数。比如说"112221"就是3段,分别是"11" "222" "1"

  一开始给出初始染色情况。

  n<=100000,m<=100000


题解

  首先树链剖分,很明显。

  然后线段树维护区间颜色。

  我们可以写一个结构体,方便色段操作。

  结构体保存4个值:当前色段的颜色总数v,左端和右端颜色:L,R;以及一个标记add:对于线段树,可以用作lazy标记,而对于色段的求和,可以用作空色段的标记(-2);

  那么色段相加就可以也一个运算符重载。这样很方便。

struct Tree{
int add,v,L,R;
Tree (){}
Tree (int x,int a,int b,int c){
add=x,v=a,L=b,R=c;
}
}t[N*4];
Tree operator + (Tree a,Tree b){
if (a.add==-2)
return b;
if (b.add==-2)
return a;
return Tree(-1,a.v+b.v-(a.R==b.L),a.L,b.R);
}

  然后就是线段树的维护了。

  维护很简单,add标记打一打就可以了。

  查询也很简单。反正空颜色段为(-2,0,0,0),合并结果就是把两个色段加起来。

  对于在树上取多段链,首先对于两个纵向的链我们求出色段。

  然后最终两个点会到同一条链上。(如果没看懂这个,那么您还得重新学学树剖)

  然后随便选一个色段翻转一下(你喜欢那个就那个,比如我翻转了上面的那个),然后再求出这两个点之间的色段,全部加起来就可以了。


代码

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=100005;
struct Gragh{
int cnt,y[N*2],nxt[N*2],fst[N];
void clear(){
cnt=0;
memset(fst,0,sizeof fst);
}
void add(int a,int b){
y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
}
}g;
struct Tree{
int add,v,L,R;
Tree (){}
Tree (int x,int a,int b,int c){
add=x,v=a,L=b,R=c;
}
}t[N*4];
Tree operator + (Tree a,Tree b){
if (a.add==-2)
return b;
if (b.add==-2)
return a;
return Tree(-1,a.v+b.v-(a.R==b.L),a.L,b.R);
}
int n,m,v[N],fa[N],size[N],depth[N],son[N],top[N],p[N],ap[N],cnp;
void Get_Gen_Info(int rt,int pre,int d){
fa[rt]=pre,size[rt]=1,son[rt]=-1,depth[rt]=d;
for (int i=g.fst[rt];i;i=g.nxt[i])
if (g.y[i]!=pre){
int s=g.y[i];
Get_Gen_Info(s,rt,d+1);
size[rt]+=size[s];
if (son[rt]==-1||size[s]>size[son[rt]])
son[rt]=s;
}
}
void Get_Pos(int rt,int tp){
top[rt]=tp,p[rt]=++cnp,ap[cnp]=rt;
if (son[rt]==-1)
return;
else
Get_Pos(son[rt],tp);
for (int i=g.fst[rt];i;i=g.nxt[i]){
int s=g.y[i];
if (s!=son[rt]&&s!=fa[rt])
Get_Pos(s,s);
}
}
void pushup(int rt){
t[rt]=t[rt<<1]+t[rt<<1|1];
}
void build(int rt,int le,int ri){
t[rt].add=-1;
if (le==ri){
t[rt].L=t[rt].R=v[ap[le]];
t[rt].v=1;
return;
}
int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
build(ls,le,mid);
build(rs,mid+1,ri);
pushup(rt);
}
void pushdown(int rt){
int ls=rt<<1,rs=ls|1;
int &a=t[rt].add;
if (a==-1)
return;
t[ls].L=t[rs].L=t[ls].R=t[rs].R=a;
t[ls].v=t[rs].v=1;
t[ls].add=t[rs].add=a;
a=-1;
}
void update(int rt,int le,int ri,int xle,int xri,int v){
if (ri<xle||le>xri)
return;
if (xle<=le&&ri<=xri){
t[rt].add=t[rt].L=t[rt].R=v;
t[rt].v=1;
return;
}
pushdown(rt);
int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
update(ls,le,mid,xle,xri,v);
update(rs,mid+1,ri,xle,xri,v);
pushup(rt);
}
Tree query(int rt,int le,int ri,int xle,int xri){
if (ri<xle||le>xri)
return Tree(-2,0,0,0);
if (xle<=le&&ri<=xri)
return t[rt];
pushdown(rt);
int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
return query(ls,le,mid,xle,xri)+query(rs,mid+1,ri,xle,xri);
}
void Tupdate(int a,int b,int c){
int f1=top[a],f2=top[b];
while (f1!=f2){
if (depth[f1]<depth[f2])
swap(f1,f2),swap(a,b);
update(1,1,n,p[f1],p[a],c);
a=fa[f1],f1=top[a];
}
if (depth[a]>depth[b])
swap(a,b);
update(1,1,n,p[a],p[b],c);
}
int solve(int a,int b){
int f1=top[a],f2=top[b];
Tree r1(-2,0,0,0),r2(-2,0,0,0);
while (f1!=f2){
if (depth[f1]<depth[f2])
swap(f1,f2),swap(a,b),swap(r1,r2);
r1=query(1,1,n,p[f1],p[a])+r1;
a=fa[f1],f1=top[a];
}
if (depth[a]>depth[b])
swap(a,b),swap(r1,r2);
swap(r1.L,r1.R);
return (r1+query(1,1,n,p[a],p[b])+r2).v;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&v[i]);
g.clear();
for (int i=1,a,b;i<n;i++){
scanf("%d%d",&a,&b);
g.add(a,b);
g.add(b,a);
}
cnp=0;
Get_Gen_Info(1,0,0);
Get_Pos(1,1);
build(1,1,n);
for (int i=1;i<=m;i++){
char ch[2];
int a,b,c;
scanf("%s%d%d",ch,&a,&b);
if (ch[0]=='C'){
scanf("%d",&c);
Tupdate(a,b,c);
}
else
printf("%d\n",solve(a,b));
}
return 0;
}

  

BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分的更多相关文章

  1. 洛谷 P2486 [SDOI2011]染色 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...

  2. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  3. bzoj-2243 2243: [SDOI2011]染色(树链剖分)

    题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6267  Solved: 2291 Descript ...

  4. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

  5. BZOJ 2243: [SDOI2011]染色 [树链剖分]

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6651  Solved: 2432[Submit][Status ...

  6. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5020  Solved: 1872[Submit][Status ...

  7. [SDOI2011]染色 树链剖分

    LG传送门 我写这道题的题解主要是因为洛谷上的题解要么讲的不清要么代码丑滑稽,导致初学时的我调了很久,所以想发个题解方便后来人. 由于要维护的信息还是具有区间可加性,只需要记录一下每个区间的左右端点颜 ...

  8. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  9. BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并

    2243: [SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数 ...

随机推荐

  1. TestNg失败重试机制

    TestNg提供了失败重试接口IRetryAnalyzer,需要实现retry方法: package com.shunhe.testngprac.retry; import org.testng.IR ...

  2. DTP协议攻击

    DTP协议 动态中继协议DTP(Dynamic Trunking Protocol)是一种Cisco私有协议.DTP用于两台交换机的直连二层端口探测对端的配置,自动协商出二层端口的链路类型和以太网封装 ...

  3. C# 摇奖机实例(线程)

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  4. CF1066D Boxes Packing

    传送门 这题为什么要用二分呢?/huaji 首先可以\(O(n)\)预处理出从某个物品\(i\)开始放,只放一个盒子,能放的最后物品的位置\(j\),只要用两个指针维护左右端点,每次移动一下左端点同时 ...

  5. luogu P2508 [HAOI2008]圆上的整点

    传送门 推荐去bzoj看个视频了解一下 不要妄想视频直接告诉你题解 但是视频告诉了你后面要用的东西 首先我们要求的是\(x^2+y^2=n^2(x,y\in Z)\)的\((x,y)\)对数,可以转化 ...

  6. vue插件开发实践与要点

    其实就跟组件差不多意思,组件也可以实现相关的效果,但要在用到的地方都引用插件就可以全局注册,不需引用 试着撸一个插件,有2个功能,提示和对话框 网上找了个toast插件的代码,改了改,扩展加了个dia ...

  7. Native、Web App、Hybrid、React Native(简称RN)、Weex 间的异同点。

    App常用开发模式简介 此处App为应用application,并非我们通常讲的手机App. 常用的几种APP开发模式-脑图 Native App 传统的原生App开发模式,有iOS和aOS两大系统, ...

  8. 访问tp3.2的项目时出现No input file specified.的解决办法

    解决办法很简单如下: 打开.htaccess 在RewriteRule 后面的index.php教程后面添加一个“?” 原来的代码如下 <IfModule mod_rewrite.c> O ...

  9. 北洋UAM-05LX(网口系列适用)ROS节点

    参考创客智造ROS与激光雷达入门教程 说明: 介绍ROS如何接入Hokuyo网口的雷达及基本使用 测试雷达:UAM-05LX采用太网接口,如果型号是USB口的参考教程 ros wiki: http:/ ...

  10. Xtion pro live OpenNI2.2 Nite 2.2 安装配置1.0

    1. 安装ubuntu14.04依赖项 $ sudo ln -s /lib/x86_64-linux-gnu/libudev.so.1.3.5 /lib/x86_64-linux-gnu/libude ...