「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 ...
随机推荐
- VirtualBox修改UUID实现虚拟硬盘的重复利用
其实,记录这个是为了留给自己看.每次用每次查,已经老到什么东西都记不住了.本次查询是从这里(VirtualBox 修改UUID实现虚拟硬盘复制)获得帮助的,感谢. 在VirtualBox把一个已经使用 ...
- Linux内存管理 (9)mmap
专题:Linux内存管理专题 关键词:文件映射.匿名映射.私有映射.共享映射 mmap/munmap是常用的一个系统调用,使用场景是:分配内存.读写大文件.连接动态库文件.多进程间共享内存. 更详细解 ...
- 一、TensorFlow初探
目录 计算模型 数据模型 运行模型 TensorFlow及神经网络 import tensorflow as tf a = tf.constant([1.0, 2.0], name='a', dtyp ...
- VUE中 style scoped 修改原有样式
作用域CSS 当<style>标记具有该scoped属性时,其CSS将仅应用于当前组件的元素.这类似于Shadow DOM中的样式封装.它有一些警告,但不需要任何polyfill.通过使用 ...
- Elasticsearch通关教程(五):如何通过SQL查询Elasticsearch
前言 这篇博文本来是想放在全系列的大概第五.六篇的时候再讲的,毕竟查询是在索引创建.索引文档数据生成和一些基本概念介绍完之后才需要的.当前面的一些知识概念全都讲解完之后再讲解查询是最好的,但是最近公司 ...
- FineUIPro v5.1.0 发布了!
FineUIPro v5.1.0 已发布,这已经是自 2014 年以来的第 31 个版本,4 年来精雕细琢,只为你来! 上个大版本新增了响应式布局,而这个版本主要是BUG修正,此外还增加了树控件的级联 ...
- 这段代码,c 1秒,java 9秒,c# 14秒,而python。。。
哎,不得不说最近见得键盘侠客太多了,做程序员没两天总是喜欢上嘴唇触天,下嘴唇碰地的吹. 自己分明都没用过几门语言,就对各门语言评头论足说三道四,这么语言多好那门语言有多烂. 可能是随着时间也变得没那么 ...
- Swagger 配置
放行 , 不拦截. @Configuration open class MyWebMvcConfig : WebMvcConfigurationSupport() { override fun add ...
- mapreduce map 的个数
在map阶段读取数据前,FileInputFormat会将输入文件分割成split.split的个数决定了map的个数.影响map个数(split个数)的主要因素有: 1) 文件的大小.当块(dfs. ...
- 删除a表中和b表相同的数据
删除a表中和b表相同的数据 - 冯索的专栏 - CSDN博客https://blog.csdn.net/wugouzi/article/details/9374329 oracle 查找A表存在B表不 ...