[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. 使用node构建一个自己的服务器

    我们做本地服务器,经常会选择Apache.IIS或者Tomcat,当然这些最方便的算是Apache,几乎不需要配置,最多就是配置下端口,亦或者我们想不用localhost,改成其他也是可以的,只要去更 ...

  2. Python导出sql语句结果到Excel

    本文档是因为每周需要统计线上数据库中客户新增资源,手动执行实在是麻烦,就写了个脚本导出到Excel,顺便发一封邮件. (当然这不是线上的真实脚本,不过根据个人需求稍微修改下,还是可以直接用的.拿去不谢 ...

  3. diskimage-builder-command

    yum -y install python-virtualenv.noarch virtualenv ~/dib-virtualenv . ~/dib-virtualenv/bin/activate ...

  4. Opencv3.1.0安装包

    这个资源是Opencv3.1.0安装包,包括Windows软件包,Android软件包,IOS软件包,还有opencv的源代码:需要的下载吧. 点击下载

  5. Java分布式数据导出实践

    伴随业务发展日益剧增,对数据的要求越来越多也越来越高. 用户在浏览器发起导出请求--web服务器接收请求--请求后台获取数据--数据统计后生成excel或其他图标--响应给客户端 整个过程至少5步,才 ...

  6. 【bzoj3669】[Noi2014]魔法森林 Kruskal+LCT

    原文地址:http://www.cnblogs.com/GXZlegend/p/6797748.html 题目描述 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看 ...

  7. 命令__shell变量$#,$@,$0,$1,$2的含义解释

    linux中shell变量$#,$@,$0,$1,$2的含义解释:变量说明:$$ Shell本身的PID(ProcessID)$! Shell最后运行的后台Process的PID$? 最后运行的命令的 ...

  8. Git的优点

    没有网络时也可以使用版本控制系统,这点svn做不到,如果你一直有网络,这个可以忽略: git由于所有版本都在本地的.git目录数据库中,因此它可以用指针随时改变指向,指向不同的版本,把它作为最新的he ...

  9. shell-总结【摘录】

    阅读目录 1. Shell简介 2. 几种常见的Shell 3. 编译型语言和解释型语言的区别 4. 什么时候使用Shell? 5. 第一个Shell脚本 6. Shell变量 7.Shell特殊变量 ...

  10. java合并两个有序数组的算法(抛砖引玉)

    前几天看见一道面试题中要将两个有序数组合并成一个新的有序数组,首先使用了嵌套循环,之后想那样效率太低,又想出了以下思路,和大家分享下,如果有更好的方法,请留言指教: 思路: 1.新建一个数组大小为fi ...