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 ...
随机推荐
- default配置页面一级菜单用于进入二级菜单
- Comet OJ - Contest #0
A:化成x-√n=y+z-√4yz的形式,则显然n是完全平方数时有无数组解,否则要求n=4yz,暴力枚举n的因数即可.注意判断根号下是否不小于0. #include<iostream> # ...
- 云服务器搭建在线ssh终端GateOne
由于公司在使用内网和安全桌面,不能在安全桌面中安装Xshell的ssh终端,所有想操作个人公网服务器很困难. 查阅发现,使用GateOne可以在服务器上搭建一个在线的ssh工具.使用体验友好,可以满足 ...
- 洛谷P1074 靶形数独(算竞进阶习题)
还是数独.. 比上一个多了个分数矩阵,其实没什么差别,但是数据好像水了许多... #include <bits/stdc++.h> #define INF 0x3f3f3f3f using ...
- 【XSY1098】第k小 可持久化trie
题目描述 给你一个长度为\(n\)数列\(a\),有\(m\)次操作: \(1~x\):把所有数异或\(x\) \(2~x\):把所有数与\(x\) \(3~x\):把所有数或\(x\) \(4~l~ ...
- git回滚部分文件到某个版本
reset 命令只能将整个版本的代码一起回滚,需要使用checkout 命令,可以还原部分文件到某一版本 格式为:git checkout [<branch>] [file] 1.首先使用 ...
- php 部署在iis HTTP 错误 500.0 - Internal Server Error 无法在<fastCGI>应用程序配置中找到<handler> scriptProcessor
原因,从A服务器复制一个部署在IIS上的PHP项目,根节点指向 publc/web.config 把里面涉及的 php路径改成正确的即可
- Mysql 数据备份导出
mysqldump导出整个数据库mysqldump --single-transaction --skip-lock-tables -uDBUSER -pDBPASSWD -hDBIP \--defa ...
- Hdoj 1232.畅通工程 题解
Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可以实现交通 ...
- expect交互式安装软件
公司一些宿主机需要安装软件,吴老师要求写一个安装脚本: 脚本思路:首先要把安装的包拷贝到每台机器上,然后要让每台机器都运行一次安装命令:就想到了应用scp.ssh命令,但这两个命令需要输入对端密码,需 ...