洛谷P2486 [SDOI2011]染色
题目描述

输入输出格式
输入格式:

输出格式:
对于每个询问操作,输出一行答案。
输入输出样例
输入样例#1:
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
输出样例#1:
3
1
2
说明


思路:对于题目中的操作\(1\),我们可以用树链剖分来实现,就是树链剖分的基本操作,难点就在于操作\(2\),这个操作是要求求任意两点间的颜色段数量,单纯的用线段树维护区间和肯定是不行的,那么就考虑去重,去重机制是怎样的呢?就是我们记录一个\(lc\)表示一个区间的左端点颜色是什么,\(rc\)表示一个区间的右端点颜色是什么,但我们合并左右区间时,如果\(lc[rs]=rc[ls]\),那么这时候就会出现重复,\(ans\)就要\(-1\)。还有就是在进行树链剖分的时候,在不断往上跳的过程中也会出现类似的重复,具体实现看代码。
代码:
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<iostream>
#define maxn 100007
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
int n,m,head[maxn],d[maxn],size[maxn],son[maxn],w[maxn];
int cnt,num,top[maxn],sum[maxn<<2],lazy[maxn<<2];
int lc[maxn<<2],rc[maxn<<2],fa[maxn],id[maxn],a[maxn];
char s;
inline int qread() {
char c=getchar();int num=0,f=1;
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) num=num*10+c-'0';
return num*f;
}
struct node {
int v,nxt;
}e[maxn<<1];
inline void ct(int u, int v) {
e[++num].v=v;
e[num].nxt=head[u];
head[u]=num;
}
void dfs1(int u, int f) {
size[u]=1;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v!=f) {
d[v]=d[u]+1;
fa[v]=u;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
}
void dfs2(int u, int t) {
id[u]=++cnt;
a[cnt]=w[u];
top[u]=t;
if(son[u]) dfs2(son[u],t);
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
inline void pushup(int rt) {
sum[rt]=sum[ls]+sum[rs]-(lc[rs]==rc[ls]);
rc[rt]=rc[rs];
lc[rt]=lc[ls];
}
void build(int rt, int l, int r) {
if(l==r) {
sum[rt]=1;
lc[rt]=rc[rt]=a[l];
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(rt);
}
inline void pushdown(int rt) {
if(lazy[rt]) {
sum[ls]=sum[rs]=1;
lazy[ls]=lazy[rs]=lc[ls]=lc[rs]=rc[ls]=rc[rs]=lazy[rt];
lazy[rt]=0;
}
}
void modify(int rt, int l, int r, int L, int R, int val) {
if(L>r||R<l) return;
if(L<=l&&r<=R) {
sum[rt]=1;
lc[rt]=rc[rt]=lazy[rt]=val;
return;
}
pushdown(rt);
int mid=(l+r)>>1;
if(L<=mid) modify(ls,l,mid,L,R,val);
if(R>mid) modify(rs,mid+1,r,L,R,val);
pushup(rt);
}
int csum(int rt, int l, int r, int L, int R) {
if(L>r||R<l) return 0;
if(L<=l&&r<=R) return sum[rt];
pushdown(rt);
int mid=(l+r)>>1;
int ans=0,js=0;
if(L<=mid) ans+=csum(ls,l,mid,L,R),js++;
if(R>mid) ans+=csum(rs,mid+1,r,L,R),js++;
if(js==2) ans-=(rc[ls]==lc[rs]);
return ans;
}
int cx(int rt, int l, int r, int L) {
if(l==r) return lc[rt];
int mid=(l+r)>>1;
pushdown(rt);
if(L<=mid) return cx(ls,l,mid,L);
else return cx(rs,mid+1,r,L);
}
void cal(int x, int y, int val) {
int fx=top[x],fy=top[y];
while(fx!=fy) {
if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
modify(1,1,cnt,id[fx],id[x],val);
x=fa[fx],fx=top[x];
}
if(id[x]>id[y]) swap(x,y);
modify(1,1,cnt,id[x],id[y],val);
}
int query(int x, int y) {
int fx=top[x],fy=top[y],ans=0;
int ans1=0,ans2=0;
while(fx!=fy) {
if(d[fx]<d[fy]) swap(x,y),swap(fx,fy),swap(ans1,ans2);
ans+=csum(1,1,cnt,id[fx],id[x]);
ans-=(cx(1,1,cnt,id[x])==ans1);
ans1=cx(1,1,cnt,id[fx]);
x=fa[fx],fx=top[x];
}
if(id[x]>id[y]) swap(x,y),swap(ans1,ans2);
ans+=csum(1,1,cnt,id[x],id[y]);
if(cx(1,1,cnt,id[x])==ans1) --ans;
if(cx(1,1,cnt,id[y])==ans2) --ans;
return ans;
}
int main() {
n=qread(),m=qread();
for(int i=1;i<=n;++i) w[i]=qread();
for(int i=1,u,v;i<n;++i) {
u=qread(),v=qread();
ct(u,v);ct(v,u);
}
d[1]=1;dfs1(1,0);dfs2(1,1);build(1,1,n);
for(int i=1,x,y,c;i<=m;++i) {
cin>>s;x=qread(),y=qread();
if(s=='C') {
c=qread();
cal(x,y,c);
}
else printf("%d\n",query(x,y));
}
return 0;
}
洛谷P2486 [SDOI2011]染色的更多相关文章
- 洛谷 P2486 [SDOI2011]染色 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...
- 洛谷 P2486 [SDOI2011]染色/bzoj 2243: [SDOI2011]染色 解题报告
[SDOI2011]染色 题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同 ...
- 洛谷 P2486 [SDOI2011]染色 LCT
Code: #include <cstdio> //SDOI2010 染色 #include <algorithm> #include <cstring> #inc ...
- 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...
- 洛谷 P2486 [SDOI2011]染色(树链剖分+线段树)
题目链接 题解 比较裸的树链剖分 好像树链剖分的题都很裸 线段树中维护一个区间最左和最右的颜色,和答案 合并判断一下中间一段就可以了 比较考验代码能力 Code #include<bits/st ...
- 洛谷 P2486 [SDOI2011]染色
题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例#1: 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C ...
- 洛谷P2486 [SDOI2011]染色(树链剖分+线段树判断边界)
[题目链接] [思路]: 涉及到树上区间修改操作,所以使用树链剖分,涉及到区间查询,所以使用线段树. update操作时,就正常操作,难点在于query操作的计数. 因为树链剖分的dfs序只能保证一条 ...
- 洛谷$P2486\ [SDOI2011]$染色 线段树+树链剖分
正解:线段树+树链剖分 解题报告: 传送门$QwQ$ 其实是道蛮板子的题,,,但因为我写得很呆然后写了贼久之后发现想法有问题要重构,就很难受,就先写个题解算了$kk$ 考虑先跑个树剖,然后按$dfn$ ...
- BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...
随机推荐
- hihocoder-1285 智力竞赛(区间dp)
智力竞赛 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi.小Ho还有被小Hi强拉来的小Z,准备组队参加一个智力竞赛.竞赛采用过关制,共计N个关卡.在第i个关卡中,小 ...
- LG3533 [POI2012]RAN-Rendezvous
2791: [Poi2012]Rendezvous Time Limit: 25 Sec Memory Limit: 128 MBSubmit: 259 Solved: 160[Submit][S ...
- 洛谷【P1236】算24点
我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html 题目传送门:https://www.luogu.org/problemnew/show/P ...
- Azure自动化部署服务 (1)
Azure中已经发布了自动化部署服务的PaaS功能. 本文将介绍自动化服务Automation初始化过程. 在Azure Management Portal上左边可以看到Azure的各种服务,其中一项 ...
- CCS V5 使用教程三:程序调试
官网教程 新建调试工程 输入以下源码: #include <stdio.h> #include <c6x.h> ]; void main(void) { unsigned ; ...
- MongoDB优化之二:常见优化方法
四个方面进行 cpu/io 方面的优化处理: 1.集群架构上进行读写分离.所有查询优先考虑在从库上读取,写操作在主库上执行.避免主库混合读写压力过大,也减少主库上读写记录的锁冲突. connectio ...
- js之翻牌游戏中的一个深刻感悟
先“上菜”: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
- AJAX经常遇到的那些问题
本文主要介绍了AJAX工作原理以及在面试题经常会遇到的问题,目录如下: 什么是Ajax 为什么要使用Ajax? Ajax特点? AJAX优缺点? Ajax流程? XMLhttprequest对象 AJ ...
- 【253】◀▶IEW-Unit18
Unit 18 International Events 1.model1对应题目分析 The Olympic Games is a major international sporting even ...
- TortoiseSVN 日常操作指南
TortoiseSVN A Subversion client for Windows Stefan Küng Lübbe Onken Simon Large 2005/01/17 19:09:21 ...