【SDOI 2011】染色
【题目链接】
【算法】
树链剖分
【代码】
本题,笔者求最近公共祖先并没有用树链剖分“往上跳”的方式,而是用倍增法。笔者认为这样比较好写,代码可读性
比较高
此外,笔者的线段树并没有用懒惰标记,只要当前访问节点的线段总数为1,那么就下传
#include<bits/stdc++.h>
using namespace std;
#define MAXLOG 18
const int MAXN = 1e5 + ; int i,n,m,timer,x,y,c,t;
int dep[MAXN],fa[MAXN],size[MAXN],son[MAXN],
dfn[MAXN],top[MAXN],val[MAXN],pos[MAXN],anc[MAXN][MAXLOG];
vector<int> e[MAXN];
char opt[]; struct SegmentTree {
struct Node {
int l,r,sum,lcover,rcover;
} Tree[MAXN*];
inline void push_up(int index) {
Tree[index].lcover = Tree[index<<].lcover;
Tree[index].rcover = Tree[index<<|].rcover;
Tree[index].sum = Tree[index<<].sum + Tree[index<<|].sum;
if (Tree[index<<].rcover == Tree[index<<|].lcover) Tree[index].sum--;
}
inline void push_down(int index) {
Tree[index<<].sum = Tree[index<<|].sum = ;
Tree[index<<].lcover = Tree[index<<].rcover = Tree[index].lcover;
Tree[index<<|].lcover = Tree[index<<|].rcover = Tree[index].rcover;
}
inline void build(int index,int l,int r) {
int mid;
Tree[index].l = l;
Tree[index].r = r;
if (l == r) {
Tree[index].lcover = Tree[index].rcover = val[pos[l]];
Tree[index].sum = ;
return;
}
mid = (l + r) >> ;
build(index<<,l,mid);
build(index<<|,mid+,r);
push_up(index);
}
inline void modify(int index,int l,int r,int val) {
int mid;
if (Tree[index].l == l && Tree[index].r == r) {
Tree[index].lcover = Tree[index].rcover = val;
Tree[index].sum = ;
return;
}
if (Tree[index].sum == ) push_down(index);
mid = (Tree[index].l + Tree[index].r) >> ;
if (mid >= r) modify(index<<,l,r,val);
else if (mid + <= l) modify(index<<|,l,r,val);
else {
modify(index<<,l,mid,val);
modify(index<<|,mid+,r,val);
}
push_up(index);
}
inline int query(int index,int l,int r) {
int mid,t;
if (Tree[index].l == l && Tree[index].r == r) return Tree[index].sum;
if (Tree[index].sum == ) push_down(index);
mid = (Tree[index].l + Tree[index].r) >> ;
if (mid >= r) return query(index<<,l,r);
else if (mid + <= l) return query(index<<|,l,r);
else {
t = ;
if (Tree[index<<].rcover == Tree[index<<|].lcover) t = ;
return query(index<<,l,mid) + query(index<<|,mid+,r) - t;
}
}
inline int get(int index,int pos) {
int mid;
if (Tree[index].l == Tree[index].r) return Tree[index].lcover;
if (Tree[index].sum == ) push_down(index);
mid = (Tree[index].l + Tree[index].r) >> ;
if (mid >= pos) return get(index<<,pos);
else return get(index<<|,pos);
}
} T;
inline void dfs1(int x) {
int i,y;
anc[x][] = fa[x];
for (i = ; i < MAXLOG; i++) {
if (dep[x] < ( << i)) break;
anc[x][i] = anc[anc[x][i-]][i-];
}
size[x] = ;
for (i = ; i < e[x].size(); i++) {
y = e[x][i];
if (fa[x] != y) {
dep[y] = dep[x] + ;
fa[y] = x;
dfs1(y);
size[x] += size[y];
if (size[y] > size[son[x]]) son[x] = y;
}
}
}
inline void dfs2(int x,int tp) {
int i,y;
dfn[x] = ++timer;
pos[timer] = x;
top[x] = tp;
if (son[x]) dfs2(son[x],tp);
for (i = ; i < e[x].size(); i++) {
y = e[x][i];
if (fa[x] != y && son[x] != y)
dfs2(y,y);
}
}
inline int lca(int x,int y) {
int i,t;
if (dep[x] > dep[y]) swap(x,y);
t = dep[y] - dep[x];
for (i = ; i <= MAXLOG - ; i++) {
if (t & ( << i))
y = anc[y][i];
}
if (x == y) return x;
for (i = MAXLOG - ; i >= ; i--) {
if (anc[x][i] != anc[y][i]) {
x = anc[x][i];
y = anc[y][i];
}
}
return anc[x][];
}
inline void modify(int x,int y,int c) {
int tx = top[x],
ty = top[y];
while (tx != ty) {
T.modify(,dfn[tx],dfn[x],c);
x = fa[tx]; tx = top[x];
}
T.modify(,dfn[y],dfn[x],c);
}
inline int query(int x,int y) {
int tx = top[x],
ty = top[y],ans = ;
while (tx != ty) {
ans += T.query(,dfn[tx],dfn[x]);
if (T.get(,dfn[tx]) == T.get(,dfn[fa[tx]])) ans--;
x = fa[tx]; tx = top[x];
}
ans += T.query(,dfn[y],dfn[x]);
return ans;
} int main() { scanf("%d%d",&n,&m);
for (i = ; i <= n; i++) scanf("%d",&val[i]);
for (i = ; i < n; i++) {
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
} dfs1();
dfs2(,);
T.build(,,timer); while (m--) {
scanf("%s",opt);
if (opt[] == 'C') {
scanf("%d%d%d",&x,&y,&c);
t = lca(x,y);
modify(x,t,c); modify(y,t,c);
} else {
scanf("%d%d",&x,&y);
t = lca(x,y);
printf("%d\n",query(x,t)+query(y,t)-);
}
} return ;
}
【SDOI 2011】染色的更多相关文章
- [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】
题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...
- BZOJ 2243 SDOI 2011染色
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 算法讨论: 树链剖分把树放到线段树上.然后线段树的每个节点要维护的东西有左端点的颜色 ...
- [SDOI 2011]染色
Description 题库链接 给定一棵有 \(n\) 个节点的无根树和 \(m\) 个操作,操作有 \(2\) 类: 将节点 \(a\) 到节点 \(b\) 路径上所有点都染成颜色 \(c\) : ...
- 解题: SDOI 2011 染色
题面 强行把序列问题通过树剖套在树上...算了算是回顾了一下树剖的思想=.= 每次树上跳的时候注意跳的同时维护当前拼出来的左右两条链的靠上的端点,然后拼起来的时候讨论一下拼接点,最后一下左右两边的端点 ...
- 【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法
BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,, 现在才会hash是不是太弱了,,, #include<cmath ...
- [bzoj2286][Sdoi 2011]消耗战
[bzoj2286]消耗战 标签: 虚树 DP 题目链接 题解 很容易找出\(O(mn)\)的做法. 只需要每次都dp一遍. 但是m和n是同阶的,所以这样肯定会T的. 注意到dp的时候有很多节点是不需 ...
- [SDOI 2011]黑白棋
Description 题库链接 给出一个 \(1\times n\) 的棋盘,棋盘上有 \(k\) 个棋子,一半是黑色,一半是白色.最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 \( ...
- [SDOI 2011]消耗战
Description 题库链接 给你一棵 \(n\) 个节点根节点为 \(1\) 的有根树,有边权. \(m\) 次询问,每次给出 \(k_i\) 个关键点.询问切断一些边,使这些点到根节点不连通, ...
- [SDOI 2011]计算器
Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数: 3.给 ...
随机推荐
- 【数学+枚举】OpenJ_POJ - C17J Pairs
https://vjudge.net/contest/171652#problem/J [题意] 问有多少个正整数对(x,y),使得存在正整数p,q满足 1 <= T <= 15 1 &l ...
- Codevs 1695 Windows2013
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 话说adamyi编的Windows 2013超时了(- -!),所以他不得不在自 ...
- [bzoj4006][JLOI2015]管道连接_斯坦纳树_状压dp
管道连接 bzoj-4006 JLOI-2015 题目大意:给定一张$n$个节点$m$条边的带边权无向图.并且给定$p$个重要节点,每个重要节点都有一个颜色.求一个边权和最小的边集使得颜色相同的重要节 ...
- 清北省选 DAY last 集锦
这是题目描述的链接: http://lifecraft-mc.com/wp-content/uploads/2018/03/problems1.pdf (虽然这次没去清北,但还是厚颜无耻的做了一下这套 ...
- Codeforces Round Edu 36
A.B.C 略 D(dfs+强连通分量) 题意: 给出一个n(n<=500)点m(m<=100000)边的有向图,问能否通过删去一条边使得该图无环. 分析: 最简单的想法就是枚举一条边删去 ...
- CSS 空中飘动的云动画
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- eclipse bug之'<>'operator is not allowed for source level below 1.7
eclipse中导入工程,报这个错'<>'operator is not allowed for source level below 1.7,把jdk改成1.7后,提示Android r ...
- Java SpringMVC实现PC端网页微信扫码支付完整版
一:前期微信支付扫盲知识 前提条件是已经有申请了微信支付功能的公众号,然后我们需要得到公众号APPID和微信商户号,这个分别在微信公众号和微信支付商家平台上面可以发现.其实在你申请成功支付功能之后,微 ...
- 盘点UML中的四种关系
生活中,我们既是独立的个体,又通过联系形成各种关系,比方说:朋友.恋人.父子,同学--于是乎,出现了神乎其神的六人定律. 那么在UML中又存在什么样的关系呢?以下我们来梳理一下. 关联(Associa ...
- SharePoint 2013 调查问卷的使用方法
SharePoint 2013 调查问卷的使用方法 1,介绍调查问卷的用法. 2.图形和全部结果. 3,控制用户仅仅能看到自己答案. 1.确认有权限,假设没有管理管理权限请向管理员申请. 站点&quo ...