2243: [SDOI2011]染色

Description

给定一棵有n个节点的无根树和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c;

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。

请你写一个程序依次完成这m个操作。

Input

第一行包含2个整数n和m,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面 行每行包含两个整数x和y,表示xy之间有一条无向边。

下面 行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

Output

对于每个询问操作,输出一行答案。

Sample Input

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

Sample Output

3

1

2

HINT

数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

题解:

  树链剖分后,在相应的标号上进行线段树操作

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double Pi = acos(-1.0);
const int N = 5e5+, M = 1e3+, mod = 1e9+, inf = 2e9; int dep[N],head[N],t=,sz[N],fa[N],indexS,top[N],pos[N];
struct ss{int to,next;}e[N*];
int n;
void add(int u,int v)
{e[t].to = v;e[t].next = head[u];head[u] = t++;} void dfs(int u) {
sz[u] = ;
dep[u] = dep[fa[u]] + ;
for(int i = head[u]; i; i = e[i].next) {
int to = e[i].to;
if(to == fa[u]) continue;
fa[to] = u;
dfs(to);
sz[u] += sz[to];
}
}
void dfs(int u,int chain) {
int k = ;
pos[u] = ++indexS;
top[u] = chain;
for(int i = head[u]; i; i = e[i].next) {
int to = e[i].to;
if(dep[to] > dep[u] && sz[to] > sz[k])
k = to;
}
if(k == ) return ;
dfs(k,chain);
for(int i = head[u]; i; i = e[i].next) {
int to = e[i].to;
if(dep[to] > dep[u] && k != to)
dfs(to,to);
}
} LL lx[N],rx[N],mx[N],sum[N],lazy[N],fposs[N];
void push_up(int i) {
sum[i] = sum[ls] + sum[rs];
if(rx[ls] == lx[rs]) sum[i]-=;
lx[i] = lx[ls];rx[i] = rx[rs];
}
void build(int i,int ll,int rr) {
if(ll == rr) {
lx[i] = fposs[ll];
rx[i] = fposs[ll];
sum[i] = ;
return ;
}
build(ls,ll,mid),build(rs,mid+,rr);
push_up(i);
}
void push_down(int i,int ll,int rr) {
if(lazy[i] && ll != rr) {
lazy[ls] = lazy[i];
lazy[rs] = lazy[i];
lx[ls] = lazy[i];
rx[ls] = lazy[i];
lx[rs] = lazy[i];
rx[rs] = lazy[i];
sum[ls] = ;
sum[rs] = ;
lazy[i] = ;
}
}
void update(int i,int ll,int rr,int x,int y,int c) {
push_down(i,ll,rr);
if(ll == x && rr == y) {
lazy[i] = c;
lx[i] = c;
rx[i] = c;
sum[i] = ;
return ;
}
if(y <= mid) update(ls,ll,mid,x,y,c);
else if(x > mid) update(rs,mid+,rr,x,y,c);
else {
update(ls,ll,mid,x,mid,c);
update(rs,mid+,rr,mid+,y,c);
}
push_up(i);
}
void change(int x,int y,int c) {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x,y);
update(,,n,pos[top[x]],pos[x],c);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
update(,,n,pos[x],pos[y],c);
}
int query(int i,int ll,int rr,int x,int y) {
push_down(i,ll,rr);
if(ll == x && rr == y) return sum[i];
if(y <= mid) return query(ls,ll,mid,x,y);
else if(x > mid) return query(rs,mid+,rr,x,y);
else return (query(ls,ll,mid,x,mid) + query(rs,mid+,rr,mid+,y) - (lx[rs] == rx[ls]));
push_up(i);
}
int color(int i,int ll,int rr,int x) {
push_down(i,ll,rr);
if(ll == rr) return lx[i];
if(x <= mid) return color(ls,ll,mid,x);
else return color(rs,mid+,rr,x);
push_up(i);
}
int query(int x,int y) {
int res = ,lastx = -,lasty = -;
while(top[x] != top[y]) {
if(dep[top[x]] > dep[top[y]]) {
res += query(,,n,pos[top[x]],pos[x]);
if(color(,,n,pos[x]) == lastx) res--;
lastx = color(,,n,pos[top[x]]);
x = fa[top[x]];
}
else {
res += query(,,n,pos[top[y]],pos[y]);
if(color(,,n,pos[y]) == lasty) res--;
lasty = color(,,n,pos[top[y]]);
y = fa[top[y]];
}
}
if(dep[x] < dep[y])res += query(,,n,pos[x],pos[y]);
else res += query(,,n,pos[y],pos[x]);
if(color(,,n,pos[x]) == lastx) res--;
if(color(,,n,pos[y]) == lasty) res--;
return res;
}
int Q,a[N],x,y;
char ch[N];
int main() {
scanf("%d%d",&n,&Q);
for(int i = ; i <= n; ++i) scanf("%d",&a[i]);
for(int i = ; i < n; ++i) {
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs();
dfs(,);
for(int i = ; i <= n; ++i) fposs[pos[i]] = a[i];
build(,,n);
while(Q--) {
int a,b,c;
scanf("%s",ch);
if(ch[] == 'Q') {
scanf("%d%d",&a,&b);
printf("%d\n",query(a,b));
}else {
scanf("%d%d%d",&a,&b,&c);
change(a,b,c);
}
}
return ;
} /*
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
*/

BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并的更多相关文章

  1. 2243: [SDOI2011]染色 树链剖分+线段树染色

    给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221”由3段组 ...

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

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

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

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

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

    B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...

  5. BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)

    题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...

  6. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  7. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  8. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  9. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  10. bzoj 2157: 旅游【树链剖分+线段树】

    裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...

随机推荐

  1. centos6 下FastDFS 在storage节点上nginx的fastdfs-nginx-module 模块编译出现的问题

    centos6.6  下FastDFS  在storage节点上   make(编译)nginx的fastdfs-nginx-module 出现如下报错: /root/fastdfs-nginx-mo ...

  2. 条款22:将成员变量声明为private(Declare data members private)

    NOTE: 1.切记将成员变量声明为private.这可赋予客户访问数据的一致性 可细微划分访问控制 允诺约束条件获得保证,并提供class作者以充分的实现弹性. 2.protected 并不比pub ...

  3. CentOS6.8下安装Docker

    原文章链接https://www.cnblogs.com/baolong/p/5743420.html. 由于在自己安装的虚拟机上打开linux终端命令行输入uname -a 以及cat /etc/r ...

  4. configparser ,subprocess , xlrd ,xlwt 模块

    一,configparser模块 ''' configparser模块: 是什么: 用于解析配置文件的模块 配置文件的定义: 用于编写保存某个软件或某个系统的一系列参数的文件 设置参数 为什么需要配置 ...

  5. Python机器学习及实践+从零开始通往Kaggle竞赛之路

    内容简介 本书面向所有对机器学习与数据挖掘的实践及竞赛感兴趣的读者,从零开始,以Python编程语言为基础,在不涉及大量数学模型与复杂编程知识的前提下,逐步带领读者熟悉并且掌握当下最流行的机器学习.数 ...

  6. 【HDU 2028】Lowest Common Multiple Plus

    Problem Description 求n个数的最小公倍数. Input 输入包含多个测试实例,每个测试实例的开始是一个正整数n,然后是n个正整数. Output 为每组测试数据输出它们的最小公倍数 ...

  7. javascript异步处理

    http://www.ruanyifeng.com/blog/2015/04/generator.html

  8. RPC实现的底层原理及应用

    摘要:RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些传输协议 ...

  9. BZOJ3408: [Usaco2009 Oct]Heat Wave 热浪

    最短路模板.选迪杰. #include<stdio.h> #include<string.h> #include<stdlib.h> #include<alg ...

  10. POJ 2391 多源多汇拆点最大流 +flody+二分答案

    题意:在一图中,每个点有俩个属性:现在牛的数量和雨棚大小(下雨时能容纳牛的数量),每个点之间有距离, 给出牛(速度一样)在顶点之间移动所需时间,问最少时间内所有牛都能避雨. 模型分析:多源点去多汇点( ...