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<cstdio>
#include<iostream>
#define N 100010
using namespace std;
int a[N],head[N],fa[N],son[N],dep[N],pos[N],top[N],lco[N*],rco[N*],sum[N*],tag[N*],n,m,sz;
struct node{
int to,pre;
};node e[N*];
void add(int i,int x,int y){
e[i].to=y;
e[i].pre=head[x];
head[x]=i;
}
void dfs1(int x){
son[x]=;
for(int i=head[x];i;i=e[i].pre){
int v=e[i].to;
if(fa[x]==v) continue;
fa[v]=x;dep[v]=dep[x]+;
dfs1(v);
son[x]+=son[v];
}
}
void dfs2(int x,int chain){
++sz;pos[x]=sz;top[x]=chain;int k=,maxn=;
for(int i=head[x];i;i=e[i].pre)
if(fa[x]!=e[i].to&&son[e[i].to]>maxn){
k=e[i].to;maxn=son[e[i].to];
}
if(!k) return;
dfs2(k,chain);
for(int i=head[x];i;i=e[i].pre)
if(fa[x]!=e[i].to&&e[i].to!=k)
dfs2(e[i].to,e[i].to);
}
void pushup(int k){
lco[k]=lco[k*];rco[k]=rco[k*+];
sum[k]=sum[k*]+sum[k*+];
if(rco[k*]==lco[k*+])sum[k]--;
}
void pushdown(int k){
if(!tag[k]) return;
tag[k*]=tag[k*+]=tag[k];
lco[k*]=lco[k*+]=tag[k];
rco[k*]=rco[k*+]=tag[k];
sum[k*]=sum[k*+]=;
tag[k]=;
}
void change(int l,int r,int k,int x,int y,int v){
if(l>=x&&r<=y){
tag[k]=lco[k]=rco[k]=v;
sum[k]=;
return;
}
pushdown(k);
int mid=l+r>>;
if(x<=mid) change(l,mid,k*,x,y,v);
if(y>mid) change(mid+,r,k*+,x,y,v);
pushup(k);
}
int query(int l,int r,int k,int x,int y){
if(l==x&&r==y)return sum[k];
pushdown(k);
int mid=l+r>>;
if(y<=mid) return query(l,mid,k*,x,y);
else if(x>mid) return query(mid+,r,k*+,x,y);
else {
int ans=query(l,mid,k*,x,mid)+query(mid+,r,k*+,mid+,y);
if(rco[k*]==lco[k*+]) ans--;
return ans;
}
}
int find(int l,int r,int k,int x){
if(l==r)return lco[k];
pushdown(k);
int mid=l+r>>;
if(x<=mid) return find(l,mid,k*,x);
else return find(mid+,r,k*+,x);
}
void xiugai(int x,int y,int v){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
change(,n,,pos[top[x]],pos[x],v);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
change(,n,,pos[x],pos[y],v);
}
int qiuhe(int x,int y){
int ans=;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans+=query(,n,,pos[top[x]],pos[x]);
if(find(,n,,pos[fa[top[x]]])==find(,n,,pos[top[x]])) ans--;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans+=query(,n,,pos[x],pos[y]);
return ans;
}
int main(){
freopen("jh.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
for(int i=;i<n;i++){
int x,y;scanf("%d%d",&x,&y);
add(i*-,x,y);add(i*,y,x);
}
dfs1();dfs2(,);
for(int i=;i<=n;i++)change(,n,,pos[i],pos[i],a[i]);
char opt[];
for(int i=;i<=m;i++){
int x,y,v;
scanf("%s%d%d",opt,&x,&y);
if(opt[]=='C'){
scanf("%d",&v);
xiugai(x,y,v);
}
else printf("%d\n",qiuhe(x,y));
}
return ;
}

染色(bzoj 2243)的更多相关文章

  1. 洛谷 P2486 [SDOI2011]染色/bzoj 2243: [SDOI2011]染色 解题报告

    [SDOI2011]染色 题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同 ...

  2. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  3. BZOJ 2243 染色(树链剖分好题)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 7971  Solved: 2990 [Submit][Stat ...

  4. [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】

    题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...

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

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

  6. bzoj 2243 [SDOI2011]染色(树链剖分,线段树)

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

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

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

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

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

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

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

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

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

随机推荐

  1. 接口接收gzip压缩数据并解压

    asp.net 接收前端gzip 压缩后的数据,接收端需要进行解压 public string GetResponseBody(HttpWebResponse response) { string r ...

  2. (十二)maven之nexus仓库的基本用法

    nexus仓库的基本用法 ① 启动nexus. 上一章有提到:https://www.cnblogs.com/NYfor2018/p/9079068.html ② 访问http://localhost ...

  3. Gym 100342I Travel Agency (Tarjan)

    题意读懂了就好做了,就是求一下点双连通分量.维护一下一颗子树的结点数,对于一个结点当u是割点的时候, 统计一下u分割的连通分量v,每得到一个连通分量的结点数cnt(v)和之前连通分量结点数sum相乘一 ...

  4. 5 Options for Distributing Your iOS App to a Limited Audience

    http://mobiledan.net/2012/03/02/5-options-for-distributing-ios-apps-to-a-limited-audience-legally/ I ...

  5. WPF中的TextBlock处理长字符串

    Xaml: <StackPanel> <TextBlock Margin="10" Foreground="Red"> This is ...

  6. Java递归获取部门树 返回jstree数据

    @GetMapping("/getDept")@ResponseBodypublic Tree<DeptDO> getDept(String deptId){ Tree ...

  7. Bootsrtap 面包屑导航(Breadcrums)

    Bootstrap面包屑导航是一种基于网站层次信息显示的方式.以博客为例,面包屑导航可以显示发布日期,类别或标签,它们表示当前页面在导航层次结构内的位置. Bootstrap面包屑导航其实是一个简单的 ...

  8. Flask——基础知识

    Flask应用程序 一个简单的Flask应用程序 # 导入flask程序 from flask import Flask # 初始化flask对象 app = Flask(__name__) # 装饰 ...

  9. iptables IP流量统计

    最后是使用ipset进行流量统计,iptaccount资料太少而且还跟网上说明的操作情况不相符,继续看源码分析组长老大都不高兴.ipset使用帮助 1. 创建ipset集合:ipset create ...

  10. Vue的响应式规则

    对象属性的响应规则 <body> <div id="root"> {{msg}} </div> </body> <script ...