bzoj2243 树链剖分
https://www.lydsy.com/JudgeOnline/problem.php?id=2243
新学的树剖,在维护的时候线段树维护区间内颜色数量以及左右两端的颜色。统计的时候区间合并时判断中间的合并点颜色是否相等,相等则ans -1
在计算答案的时候不同的链上两端跳的过程中也要注意color[top[u]]和color[fa[top[u]]]是否相等,相等则ans--
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
inline int read(){int now=;register char c=getchar();for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());return now;}
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 1e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
int head[maxn],tot;
struct Edge{
int to,next;
}edge[maxn * ];
void init(){
for(int i = ; i <= N ; i ++) head[i] = -;
tot = ;
}
void add(int u,int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
//树的信息
int dep[maxn],hson[maxn],fa[maxn],Size[maxn],color[maxn],Index[maxn],top[maxn];
int nw[maxn];
void dfs1(int t,int la){
Size[t] = ;
hson[t] = ; int MAX = ;
for(int i = head[t]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v == la) continue;
dep[v] = dep[t] + ; fa[v] = t;
dfs1(v,t);
Size[t] += Size[v];
if(Size[v] > MAX){
MAX = Size[v];
hson[t] = v;
}
}
}
int cnt = ;
void dfs2(int t,int la){
top[t] = la;
Index[t] = ++cnt;
nw[cnt] = color[t];
if(hson[t]) dfs2(hson[t],la);
for(int i = head[t]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v == hson[t] || v == fa[t]) continue;
dfs2(v,v);
}
}
//线段树
struct Tree{
int l,r;
int sum;
int lazy;
int lc,rc;
}tree[maxn << ];
void Pushup(int t){
tree[t].sum = tree[t << ].sum + tree[t << | ].sum;
tree[t].lc = tree[t << ].lc; tree[t].rc = tree[t << | ].rc;
if(tree[t << ].rc == tree[t << | ].lc) tree[t].sum--;
}
void Build(int t,int l,int r){
tree[t].lazy = ;
tree[t].l = l; tree[t].r = r;
if(tree[t].l == tree[t].r){
tree[t].sum = ;
tree[t].lc = tree[t].rc = nw[l];
return;
}
int m = (l + r) >> ;
Build(t << ,l,m); Build(t << | ,m + ,r);
Pushup(t);
}
void Pushdown(int t){
if(tree[t].lazy){
tree[t << ].lazy = tree[t << | ].lazy = tree[t].lazy;
tree[t << ].sum = tree[t << | ].sum = ;
tree[t << ].lc = tree[t << | ].lc = tree[t].lazy;
tree[t << ].rc = tree[t << | ].rc = tree[t].lazy;
tree[t].lazy = ;
}
}
void update(int t,int l,int r,int c){
if(l <= tree[t].l && tree[t].r <= r){
tree[t].lazy = c;
tree[t].sum = ;
tree[t].lc = tree[t].rc = c;
return;
}
Pushdown(t);
int m = (tree[t].l + tree[t].r) >> ;
if(r <= m) update(t << ,l,r,c);
else if(l > m) update(t << | ,l,r,c);
else{
update(t << ,l,m,c);
update(t << | ,m + ,r,c);
}
Pushup(t);
}
int query(int t,int l,int r){
if(l <= tree[t].l && tree[t].r <= r) return tree[t].sum;
Pushdown(t);
int ans = ;
int m = (tree[t].l + tree[t].r) >> ;
if(r <= m) ans = query(t << ,l,r);
else if(l > m) ans = query(t << | ,l,r);
else{
ans = query(t << ,l,m) + query(t << | ,m + ,r);
if(tree[t << ].rc == tree[t << | ].lc) ans--;
}
Pushup(t);
return ans;
}
int query(int t,int p){
if(tree[t].sum == ) return tree[t].lc;
int m = (tree[t].l + tree[t].r) >> ;
if(p <= m) return query(t << ,p);
else if(p > m) return query(t << | ,p);
}
//树链剖分
void update(int u,int v,int c){
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) swap(u,v);
update(,Index[top[u]],Index[u],c);
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u,v);
update(,Index[u],Index[v],c);
}
int Query(int u,int v){
int ans = ;
int la = ;
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) swap(u,v);
ans += query(,Index[top[u]],Index[u]);
if(query(,Index[fa[top[u]]]) == query(,Index[top[u]])) ans--;
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u,v);
ans += query(,Index[u],Index[v]);
return ans;
}
int main(){
Sca2(N,M); init();
for(int i = ; i <= N ; i ++) color[i] = read();;
for(int i = ; i < N ; i ++){
int u = read(),v = read();
add(u,v); add(v,u);
}
int root = N; dep[root] = ;
dfs1(root,-); cnt = ; dfs2(root,root);
Build(,,N);
while(M--){
char op[]; int a,b,c;
scanf("%s",op); a = read(); b = read();
if(op[] == 'C'){
c = read(); update(a,b,c);
}else{
Pri(Query(a,b));
}
}
return ;
}
bzoj2243 树链剖分的更多相关文章
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- bzoj2243树链剖分+染色段数
终于做了一道不是一眼出思路的代码题(⊙o⊙) 之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱) 实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开 ...
- bzoj2243树链剖分+区间合并
树链上区间合并的问题比区间修改要复杂,因为每一条重链在线段树上分布一般都是不连续的,所以在进行链上操作时要手动将其合并起来,维护两个端点值 处理时的方向问题:lca->u是一个方向,lca-&g ...
- [SDOI2011]染色 BZOJ2243 树链剖分+线段树
分析: 区间合并,lcol是左端点的颜色编号,rcol是右端点的颜色编号,那么我们向上合并的时候,如果左儿子的rcol等于右儿子的lcol那么区间的sum--. 另外,如果重链顶的颜色等于重链顶的父节 ...
- BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)
题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...
- [BZOJ2243][SDOI2011]染色 解题报告|树链剖分
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...
- bzoj-2243 2243: [SDOI2011]染色(树链剖分)
题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6267 Solved: 2291 Descript ...
随机推荐
- 当进行数据查询时候 要考虑创建一个model ;具备传入与输出的字段
当进行数据查询时候 要考虑创建一个model ;具备传入与输出的字段
- 基于OpenCv和swing的图片/视频展示Java实现
基于OpenCv和swing实现图片/视频的展示 图片的展示 swing展示图片,多为操作BufferedImage,这里要关注的核心是将Mat转为BufferedImage. 代码如下: publi ...
- linux下Tomcat进程shutdown不完全--解决方案
Kill进程,修改tomcat bin目录下shutdown.sh和catalina.sh文件 忽略日志中的严重警告,因为这是关闭tomcat时候引起的,正常情况下不会发生这种内存泄露情况,而且Tom ...
- 天哪又要搬家啦qvq
CSDN现在怎么这么好看了qvq 搬家回去的欲望日渐强烈... update:2019/02/25 被csdn的侧栏广告烦死了
- linux中监控CPU、内存和磁盘状态的shell脚本。(centos7)
这篇博客中所写的脚本,在实际工作中并没有什么卵用,工作中并不会用到这种脚本去监控.不过自己写一遍,可以让初学者对CPU.内存.磁盘等一些基础知识和基础命令更加了解. 1.利用vmstat工具监控CPU ...
- C# 新语法收集
内联变量 使用int.tryparst时,先要申明变量,用于out参数 int d; int.tryparse(s,out d); 使用内联变量写法可以如下.功能一样简化了写化 int.trypars ...
- [2017-7-26]Android Learning Day4
RecycleView 恩,学习Fragment的过程中的一个小实践居然用到了RecycleView!坑了我好久有木有!!好气哦,从昨晚到现在.(现在也还是一头雾水,不过照搬也会用了) 这是第一版的代 ...
- luogu5012 水の数列 (并查集+线段树)
如果我们能求出来每个区间个数的最大分值,那就可以用线段树维护这个东西 然后出答案了 然后这个的求法和(luogu4269)Snow Boots G非常类似,就是我们把数大小排个序,每次都拿<=x ...
- centos7/centos6修改系统默认语言
应用环境: 一直在使用centos7.x,系统默认的语言也是英文环境,工作内容偶遇中文,顺便搜罗修改一番,小记如下. 测试环境: 测试步骤: CentOS 7.x 1. 查看当前语言环境 [root@ ...
- 微信小程序支付(PHP后端)
1.申请开通小程序支付,我们正式开通的微信支付是在微信公众平台上,我们需要绑定之前的微信商户平台即可,这一点不过多强调 2.小程序支付开发步骤 (1).统一下单 大家看到微信的统一下单接口密密麻麻的一 ...