[SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 6870  Solved: 2546
[Submit][Status][Discuss]

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]之间。

【分析】此题的难点在于处理颜色块的个数。考虑到若两个区间合并,颜色块的个数取决于两边的个数和合并处的两个接口处颜色是否相等,相等则-1.所以对于每个线段树结点(代表区间)维护三个数组--sum[]:此区间的颜色块数;s[]:此区间左端的颜色;t[]:此区间右端的颜色。所以区间合并时,若左儿子的右端点与右儿子的左端点相等,则

sum[rt]=sum[rt*2]+sum[rt*2+1]-1,否则不-1.区间修改采用lazy[]标记。(敲了一下午,调了一晚上,最后发现是个很SB的错误,日。。。)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int N=2e5+;
const int M=N*N+;
int dep[N],siz[N],fa[N],id[N],son[N],val[N],top[N],c[N];
int num,m,n,q,tot=;
int sum[N*];
int lazy[N*],head[N],s[N*],t[N*];
struct tree {
int to,next;
} edg[N*];
void add(int u,int v) {
edg[tot].to=v;
edg[tot].next=head[u];
head[u]=tot++;
}
void dfs1(int u, int f, int d) {
dep[u] = d;
siz[u] = ;
son[u] = ;
fa[u] = f;
for (int i = head[u]; i != -; i=edg[i].next) {
int ff = edg[i].to;
if (ff == f) continue;
dfs1(ff, u, d + );
siz[u] += siz[ff];
if (siz[son[u]] < siz[ff])
son[u] = ff;
}
}
void dfs2(int u, int tp) {
top[u] = tp;
id[u] = ++num;
if (son[u]) dfs2(son[u], tp);
for (int i = head[u]; i != -; i=edg[i].next) {
int ff = edg[i].to;
if (ff == fa[u] || ff == son[u]) continue;
dfs2(ff, ff);
}
}
void Push_up(int rt) {
if(t[rt*]==s[rt*+])sum[rt]=sum[rt*]+sum[rt*+]-;
else sum[rt]=sum[rt*]+sum[rt*+];
s[rt]=s[rt*];
t[rt]=t[*rt+];
}
void Push_down(int rt) {
if(lazy[rt]) {
s[*rt]=s[*rt+]=t[*rt]=t[*rt+]=lazy[rt];
lazy[*rt]=lazy[rt];
lazy[*rt+]=lazy[rt];
sum[*rt]=sum[*rt+]=;
lazy[rt]=;
}
}
void Build(int l,int r,int rt) {
if(l==r) {
lazy[rt]=s[rt]=t[rt]=val[l];
sum[rt]=;
return;
}
Push_down(rt);
int m=(l+r)>>;
Build(lson);
Build(rson);
Push_up(rt);
}
void Update(int L,int R,int l,int r,int rt,int add) {
if(l>=L&&r<=R) {
lazy[rt]=add;
s[rt]=t[rt]=add;
sum[rt]=;
return;
}
Push_down(rt);
int m=(r+l)>>;
if(L<=m)Update(L,R,lson,add);
if(R>m) Update(L,R,rson,add);
Push_up(rt);
}
int Query(int L,int R,int l,int r,int rt) {
if(L<=l&&r<=R)return sum[rt];
Push_down(rt);
int m=(l+r)>>,ans=;
if(L<=m)ans+=Query(L,R,lson);
if(R>m)ans+=Query(L,R,rson);
if(L<=m && R>m && s[rt*+]==t[rt*])ans--;
return ans;
}
void solve(int u,int v,int add) {
int tp1 = top[u], tp2 = top[v];
while (tp1 != tp2) {
if (dep[tp1] < dep[tp2]) {
swap(tp1, tp2);
swap(u, v);
}
Update(id[tp1],id[u],,n,,add);
u = fa[tp1];
tp1 = top[u];
}
if (dep[u] > dep[v]) swap(u, v);
Update(id[u],id[v],,n,,add);
return;
}
int _find(int u,int l,int r,int rt){
if(l==r)return s[rt];
Push_down(rt);
int m=(l+r)/;
if(u<=m)return _find(u,l,m,rt*);
else return _find(u,m+,r,rt*+);
}
int Answer(int u,int v) {
int tp1 = top[u], tp2 = top[v];
int ans=;
while (tp1 != tp2) {
if (dep[tp1] < dep[tp2]) {
swap(tp1, tp2);
swap(u, v);
}
ans +=Query(id[tp1], id[u],,n,);
u = fa[tp1];
if(_find(id[tp1],,n,)==_find(id[u],,n,))ans--;
tp1 = top[u];
}
if (dep[u] > dep[v]) swap(u, v);
ans += Query(id[u], id[v],,n,);
return ans;
}
int main() {
scanf("%d%d",&n,&m);
met(head,-);
int u,v,w;
for(int i=; i<=n; i++) {
scanf("%d",&c[i]);
}
for(int i=; i<n; i++) {
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
num = ;
dfs1(,,);
dfs2(,);
for (int i = ; i <= n; i++) {
val[id[i]]=c[i];
}
Build(,num,);
char str[];
while(m--) {
scanf("%s",str);
if(str[]=='C') {
scanf("%d%d%d",&u,&v,&w);
solve(u,v,w);
} else {
scanf("%d%d",&u,&v);
printf("%d\n",Answer(u,v));
}
}
return ;
}

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. CS/BS架构的特点

    CS架构 优点: 1.有独立的客户端,安全性高 2.大部分业务都在客户端实现,可以实现很复杂的业务 缺点: 1.对环境要求高,需要安装客户端,推广速度慢 2.需要专门前后台的开发团队,维护成本高 B/ ...

  2. jenkins 连接服务器并运行脚本

    1.登录,在系统管理——节点管理——新增节点——配置从节点,添加远程工作目录,选择启动方式:通过JAVA WEB启动代理,添加JDK 2.在列表点节点,点launch下载插件,放到D:\JENKINS ...

  3. Python学习5,三级菜单实例

    _author_ = "Happyboy" data = { '北京':{ "昌平":{ "沙河":["Happyboy" ...

  4. Android动态添加和移除布局

    package com.hyang.administrator.studentproject; import android.os.Bundle; import android.support.v7. ...

  5. java中unmodifiableList方法的应用场景

    java对象中primitive类型变量可以通过不提供set方法保证不被修改,但对象的List成员在提供get方法后,就可以随意add.remove改变其结构,这不是希望的结果.网上看了下,发现Col ...

  6. P3200 [HNOI2009]有趣的数列

    题目描述 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所有的奇数项满足a1<a3<...<a2n ...

  7. java链接数据库--Mysql

    /************************************************************************* > File Name: Mysql.jav ...

  8. Codeforces Round #352 (Div. 2) C

    C. Recycling Bottles time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  9. [CQOI2018]异或序列 (莫队,异或前缀和)

    题目链接 Solution 有点巧的莫队. 考虑到区间 \([L,R]\) 的异或和也即 \(sum[L-1]~\bigoplus~sum[R]\) ,此处\(sum\)即为异或前缀和. 然后如何考虑 ...

  10. Windows7下的Run运行命令一览表

    按住Windows键(就是左边Ctrl和Alt之间那个印windows徽标的键,简称Win键)+R,即可弹出运行对话框,在里面输入黑体字符即可运行相应程序.相比XP这次新增了不少新东西. 添加/删除程 ...