「luogu2486」[SDOI2011] 染色
https://www.luogu.org/problemnew/show/P2486
轻重链剖分后,问题转化为一个链上的问题;
线段树维护区间内的颜色段数量,左端点、右端点的颜色;
线段树注意事项 {
合并时判断两个区间的相邻端点是否相同;
查询时同上,但要注意是否两段是不是都在查询区间内;
lazy_tag和更新颜色,嘻嘻嘻。
}
p.s 树上查询颜色段要判断两条链的端点是否颜色相同;
特别地,对于在同一条链上的两个节点之间的查询,要判断两个点和与它相邻点的颜色是否相同。
代码如下 :
// 15owzLy1
//luogu2486.cpp
//2018 09 26 18:38:11
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lson tl, mid, rt<<1
#define rson mid+1, tr, rt<<1|1
typedef long long ll;
typedef double db;
using namespace std; const int N = ;
struct node { int l, r, cnt; };
struct info {
int next, to;
}edge[N<<];
int head[N], dfn[N], size[N], hson[N], fa[N], dep[N], q, n;
int front[N], cl[N]; template<typename T>inline void read(T &x_) {
x_=;bool f_=;char c_=getchar();
while(c_<''||c_>''){f_|=(c_=='-');c_=getchar();}
while(c_>=''&&c_<=''){x_=(x_<<)+(x_<<)+(c_^);c_=getchar();}
x_=f_?-x_:x_;
} struct Segment_Tree {
node t[N<<]; int lazy[N<<];
inline void push_up(int rt) {
t[rt].cnt=t[rt<<].cnt+t[rt<<|].cnt;
if(t[rt<<].r==t[rt<<|].l) t[rt].cnt--;
t[rt].l=t[rt<<].l, t[rt].r=t[rt<<|].r;
}
inline void spread(int rt) {
t[rt<<].cnt=; t[rt<<|].cnt=;
t[rt<<].l=t[rt<<|].r=t[rt<<].r=t[rt<<|].l=
lazy[rt<<]=lazy[rt<<|]=lazy[rt];
lazy[rt]=;
}
void update(int del, int l, int r, int tl, int tr, int rt) {
if(l<=tl&&tr<=r) {
t[rt].cnt=; t[rt].l=t[rt].r=lazy[rt]=del;
return ;
}
if(lazy[rt]) spread(rt);
int mid=(tl+tr)>>;
if(mid>=l) update(del, l, r, lson);
if(mid<r) update(del, l, r, rson);
push_up(rt);
}
int query(int l, int r, int tl, int tr, int rt) {
if(l<=tl&&tr<=r) return t[rt].cnt;
if(lazy[rt]) spread(rt);
int mid=(tl+tr)>>, res=, k=;
if(mid>=l) res+=query(l, r, lson), ++k;
if(mid<r) res+=query(l, r, rson), ++k;
if(t[rt<<].r==t[rt<<|].l&&k>=) res--;
return res;
}
int ask_cl(int pos, int tl, int tr, int rt) {
if(tl==tr) return t[rt].l;
if(lazy[rt]) spread(rt);
int mid=(tl+tr)>>;
if(mid>=pos) return ask_cl(pos, lson);
else return ask_cl(pos, rson);
}
}T; inline void jb(int u, int v) {
edge[++edge[].to].to=v;
edge[edge[].to].next=head[u];
head[u]=edge[].to;
} void dfs(int u) {
size[u]=;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(v==fa[u]) continue;
fa[v]=u; dep[v]=dep[u]+;
dfs(v);
size[u]+=size[v];
if(size[hson[u]]<size[v]) hson[u]=v;
}
} inline void dfs_(int u, int father) {
dfn[u]=++dfn[]; front[u]=father;
if(hson[u]) dfs_(hson[u], father);
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(v==fa[u]||v==hson[u]) continue;
dfs_(v, v);
}
} inline void update(int u, int v, int del) {
while(front[u]!=front[v]) {
if(dep[front[u]]>dep[front[v]]) swap(u, v);
T.update(del, dfn[front[v]], dfn[v], , n, );
v=fa[front[v]];
}
if(dep[u]>dep[v]) swap(u, v);
T.update(del, dfn[u], dfn[v], , n, );
} inline int query(int u, int v) {
int res=, clu=-, clv=-, tmp, k=;
while(front[u]!=front[v]) {
if(dep[front[u]]>dep[front[v]])
swap(u, v), swap(clu, clv);
res+=T.query(dfn[front[v]], dfn[v], , n, );
tmp=T.ask_cl(dfn[v], , n, );
if(clv==tmp) --res;
clv=T.ask_cl(dfn[front[v]], , n, );
v=fa[front[v]];
}
if(dep[u]>dep[v])
swap(u, v), swap(clu, clv);
if(clu==T.ask_cl(dfn[u], , n, )) res--, ++k;
if(clv==T.ask_cl(dfn[v], , n, )) res--, ++k;
res+=T.query(dfn[u], dfn[v], , n, );
return res;
} int main() {
#ifndef ONLINE_JUDGE
freopen("luogu2486.in","r",stdin);
freopen("luogu2486.out","w",stdout);
#endif
int x, y, z; char opt[];
read(n), read(q);
for(int i=;i<=n;i++) read(cl[i]);
for(int i=;i<n;i++) read(x), read(y), jb(x, y), jb(y, x);
dep[]=;
dfs(); dfs_(,);
for(int i=;i<=n;i++) T.update(cl[i], dfn[i], dfn[i], , n, );
while(q--) {
scanf("%s", opt); read(x), read(y);
if(opt[]=='Q') printf("%d\n", query(x, y));
else read(z), update(x, y, z);
}
return ;
}
「luogu2486」[SDOI2011] 染色的更多相关文章
- 「HAOI2018」染色 解题报告
「HAOI2018」染色 是个套路题.. 考虑容斥 则恰好为\(k\)个颜色恰好为\(c\)次的贡献为 \[ \binom{m}{k}\sum_{i\ge k}(-1)^{i-k}\binom{m-k ...
- Loj #3111. 「SDOI2019」染色
Loj #3111. 「SDOI2019」染色 题目描述 给定 \(2 \times n\) 的格点图.其中一些结点有着已知的颜色,其余的结点还没有被染色.一个合法的染色方案不允许相邻结点有相同的染色 ...
- # 「NOIP2010」关押罪犯(二分图染色+二分答案)
「NOIP2010」关押罪犯(二分图染色+二分答案) 洛谷 P1525 描述:n个罪犯(1-N),两个罪犯之间的仇恨值为c,m对仇恨值,求怎么分配使得两件监狱的最大仇恨值最小. 思路:使最大xxx最小 ...
- 「JSOI2015」染色问题
「JSOI2015」染色问题 传送门 虽然不是第一反应,不过还是想到了要容斥. 题意转化:需要求满足 \(N + M + C\) 个条件的方案数. 然后我们就枚举三个数 \(i, j, k\) ,表示 ...
- 「UOJ351」新年的叶子
「UOJ351」新年的叶子 题目描述 有一棵大小为 \(n\) 的树,每次随机将一个叶子染黑,可以重复染,问期望染多少次后树的直径会缩小. \(1 \leq n \leq 5 \times 10^5\ ...
- 「NOI2016」区间 解题报告
「NOI2016」区间 最近思维好僵硬啊... 一上来就觉得先把区间拆成两个端点进行差分,然后扫描位置序列,在每个位置维护答案,用数据结构维护当前位置的区间序列,但是不会维护. 于是想研究性质,想到为 ...
- 「ZJOI2019」语言 解题报告
「ZJOI2019」语言 3个\(\log\)做法比较简单,但是写起来还是有点麻烦的. 大概就是树剖把链划分为\(\log\)段,然后任意两段可以组成一个矩形,就是个矩形面积并,听说卡卡就过去了. 好 ...
- 「CH6901」骑士放置
「CH6901」骑士放置 传送门 将棋盘黑白染色,发现"日"字的两个顶点刚好一黑一白,构成一张二分图. 那么我们将黑点向源点连边,白点向汇点连边,不能同时选的一对黑.白点连边. 当 ...
- 「CH6801」棋盘覆盖
「CH6801」棋盘覆盖 传送门 考虑将棋盘黑白染色,两个都无障碍的相邻的点之间连边,边的容量都为1,然后就求一次最大匹配即可 参考代码: #include <cstring> #incl ...
随机推荐
- Java 最常见的 200+ 面试题汇总
这份面试清单是我从 2015 年做 TeamLeader 之后开始收集的,一方面是给公司招聘用,另一方面是想用它来挖掘我在 Java 技术栈中的技术盲点,然后修复和完善它,以此来提高自己的技术水平.虽 ...
- 《App架构实践指南》
推荐书籍 <App 架构实践指南>
- NTT板子
不说别的. 这份NTT跑得比FFT快,不知道为什么. 以下代码针对\(10^5\)的数据范围. #include<cstdio> #include<vector> #inclu ...
- 封装的通过微信JS-SDK实现自定义分享到朋友圈或者朋友的ES6类!
引言: 我们经常在做微信H5的过程中需要自定义分享网页,这个如何实现呢?请看如下的封装的ES6类及使用说明! /** * @jssdk js对象,包括appId,timestamp,nonceStr, ...
- [官网]Using PuTTY
Previous | Contents | Next Chapter 3: Using PuTTY Section 3.1: During your session Section 3.1.1: Co ...
- Windows 通过批处理自动执行 linux服务器上面命令的办法
1. 使用putty 下载地址 https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html 直接使用 exe版本就可以 https:/ ...
- python 条件分支与循环
一.if判断: 语法一: if 条件: # 条件成立时执行的子代码块 代码1 代码2 代码3 示例: sex='female' age=18 is_beautiful=True if sex == ' ...
- [模板] dfs序, 树链剖分, 换根
树链剖分 树链剖分是一种对树的分治, 可以把树上的任意一条链分解为 \(O(\log n)\) 条在dfs序上相邻的子链, 便于数据结构(如线段树)来维护. 另外, 子树在dfs序上也是一个连续的区间 ...
- [SimplePlayer] 8. 音视频同步
音频与视频在播放当中可能会由于种种原因(如:音视频并非在同一时间开始播放,或视频由于解码任务繁重导致输出图像延迟等)导致音频与视频的播放时间出现偏差,这种就是音视频的同步问题,本文会对音视频同步进行讨 ...
- css 溢出overflow
css 溢出overflow 当一个元素被设置为固定大小,在这个元素中的内容如果超出元素的界限,就会出现溢出的现象. 通常情况下我们可以通过overflow来控制这个属性. overflow语法定义 ...