【SPOJ】QTREE6-Query on a tree VI
题解
老年选手的代码康复计划QAQ
这题又没一遍A,难受
每个节点维护这个节点子树内联通块的大小
维护所有节点轻儿子的\(g[u][0]\)表示所有轻儿子白色的联通块总数
\(g[u][1]\)表示所有轻儿子黑色联通块总数
更新一个点为新颜色的时候,是\(g[u][c[u] ^ 1] + 1\)再加上重儿子价值(如果修改后颜色相同
然后我们向上更新,修改到和父亲节点颜色相同的最浅的节点
如果改后颜色和父亲颜色不同,那么这些点都减去原来的值
否则都加上新值
然后在经过轻边的时候顺带维护一下\(g\)即可
对于找颜色相同的最浅节点,用线段树维护一个区间颜色是否相同即可
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,M;
struct node {
int to,next;
}E[MAXN * 2];
int sumE,head[MAXN],c[MAXN];
int dfn[MAXN],son[MAXN],siz[MAXN],top[MAXN],dep[MAXN],fa[MAXN],idx,seq[MAXN];
int g[MAXN][2];
void add(int u,int v) {
E[++sumE].to = v;
E[sumE].next = head[u];
head[u] = sumE;
}
void dfs1(int u) {
dep[u] = dep[fa[u]] + 1;
siz[u] = 1;
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != fa[u]) {
fa[v] = u;
dfs1(v);
siz[u] += siz[v];
if(siz[v] > siz[son[u]]) son[u] = v;
}
}
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != fa[u] && v != son[u]) {
g[u][1] += siz[v];
}
}
}
void dfs2(int u) {
dfn[u] = ++idx;seq[idx] = u;
if(!top[u]) top[u] = u;
if(son[u]) {top[son[u]] = top[u];dfs2(son[u]);}
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != fa[u] && v != son[u]) dfs2(v);
}
}
namespace seg_tr {
struct node {
int L,R;
int val,lz;
bool sc,col;
}tr[MAXN * 4];
#define lc(u) u << 1
#define rc(u) u << 1 | 1
#define val(u) tr[u].val
#define lz(u) tr[u].lz
#define sc(u) tr[u].sc
#define col(u) tr[u].col
void addlz(int u,int v) {
val(u) += v;lz(u) += v;
}
void push_down(int u) {
if(tr[u].lz) {
addlz(lc(u),tr[u].lz);
addlz(rc(u),tr[u].lz);
}
tr[u].lz = 0;
}
void update(int u) {
if(sc(lc(u)) && sc(rc(u)) && !(col(lc(u)) ^ col(rc(u)) ) ) {
sc(u) = 1;col(u) = col(lc(u));
}
else sc(u) = 0;
}
void build(int u,int l,int r) {
tr[u].L = l;tr[u].R = r;
if(l == r) {
tr[u].sc = 1;tr[u].col = c[seq[l]];
tr[u].val = siz[seq[l]];tr[u].lz = 0;
return;
}
int mid = (l + r) >> 1;
build(u << 1,l,mid);
build(u << 1 | 1,mid + 1,r);
update(u);
}
int query(int u,int p) {
if(tr[u].L == tr[u].R) return tr[u].val;
push_down(u);
int mid = (tr[u].L + tr[u].R) >> 1;
if(p <= mid) return query(lc(u),p);
else if(p > mid) return query(rc(u),p);
}
void add(int u,int l,int r,int v) {
if(tr[u].L == l && tr[u].R == r) {addlz(u,v);return;}
push_down(u);
int mid = (tr[u].L + tr[u].R) >> 1;
if(r <= mid) add(lc(u),l,r,v);
else if(l > mid) add(rc(u),l,r,v);
else {
add(lc(u),l,mid,v);
add(rc(u),mid + 1,r,v);
}
}
void change(int u,int p,int v,bool on) {
if(tr[u].L == tr[u].R) {
tr[u].val = v;
tr[u].col = on;
return;
}
push_down(u);
int mid = (tr[u].L + tr[u].R) >> 1;
if(p <= mid) change(lc(u),p,v,on);
else change(rc(u),p,v,on);
update(u);
}
int query_sc(int u,int l,int r) {
if(tr[u].L == l && tr[u].R == r) return tr[u].sc;
push_down(u);
int mid = (tr[u].L + tr[u].R) >> 1;
if(r <= mid) return query_sc(lc(u),l,r);
else if(l > mid) return query_sc(rc(u),l,r);
else {
return query_sc(lc(u),l,mid) && query_sc(rc(u),mid + 1,r) && c[seq[mid]] == c[seq[mid + 1]];
}
}
int Query(int p) {
return query(1,dfn[p]);
}
void Add(int l,int r,int v) {
add(1,l,r,v);
}
void Change(int p,int v,bool on) {
change(1,dfn[p],v,on);
}
bool Query_sc(int l,int r) {
return query_sc(1,l,r);
}
}
int Find_same_color(int u) {
while(1) {
if(seg_tr::Query_sc(dfn[top[u]],dfn[u])) {
if(top[u] == 1) return 1;
if(c[fa[top[u]]] != c[u]) return top[u];
u = fa[top[u]];
}
else {
int L = dfn[top[u]] + 1,R = dfn[u];
while(L < R) {
int mid = (L + R) >> 1;
if(seg_tr::Query_sc(mid,dfn[u])) R = mid;
else L = mid + 1;
}
return seq[L];
}
}
}
void Change_Path(int u,int v,int d) {
while(top[u] != top[v]) {
seg_tr::Add(dfn[top[u]],dfn[u],d);
g[fa[top[u]]][c[top[u]]] += d;
u = fa[top[u]];
}
seg_tr::Add(dfn[v],dfn[u],d);
if(v == top[u]) g[fa[v]][c[v]] += d;
}
void Init() {
read(N);
int u,v;
for(int i = 1 ; i <= N ; ++i) c[i] = 1;
for(int i = 1 ; i < N ; ++i) {
read(u);read(v);
add(u,v);add(v,u);
}
dfs1(1);dfs2(1);
seg_tr::build(1,1,N);
}
void Solve() {
read(M);
int op,u;
for(int i = 1 ; i <= M ; ++i) {
read(op);read(u);
if(!op) {
out(seg_tr::Query(Find_same_color(u)));enter;
}
else {
int nv = 1 + g[u][c[u] ^ 1] + (son[u] && c[son[u]] == (c[u] ^ 1) ? seg_tr::Query(son[u]) : 0);
int ov = seg_tr::Query(u);
if(u == 1) {
seg_tr::Change(u,nv,c[u] ^ 1);c[u] ^= 1;
}
else {
if(u == top[u]) {
g[fa[u]][c[u]] -= ov;
g[fa[u]][c[u] ^ 1] += nv;
}
int t = Find_same_color(fa[u]);
if(c[fa[u]] == c[u]) Change_Path(fa[u],t,-ov);
else Change_Path(fa[u],t,nv);
seg_tr::Change(u,nv,c[u] ^ 1);c[u] ^= 1;
}
}
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
return 0;
}
【SPOJ】QTREE6-Query on a tree VI的更多相关文章
- 【SPOJ】375. Query on a tree(树链剖分)
http://www.spoj.com/problems/QTREE/ 这是按边分类的. 调试调到吐,对拍都查不出来,后来改了下造数据的,拍出来了.囧啊啊啊啊啊啊 时间都花在调试上了,打hld只用了半 ...
- SPOJ 16549 - QTREE6 - Query on a tree VI 「一种维护树上颜色连通块的操作」
题意 有操作 $0$ $u$:询问有多少个节点 $v$ 满足路径 $u$ 到 $v$ 上所有节点(包括)都拥有相同的颜色$1$ $u$:翻转 $u$ 的颜色 题解 直接用一个 $LCT$ 去暴力删边连 ...
- 【SPOJ】QTREE6(Link-Cut-Tree)
[SPOJ]QTREE6(Link-Cut-Tree) 题面 Vjudge 题解 很神奇的一道题目 我们发现点有黑白两种,又是动态加边/删边 不难想到\(LCT\) 最爆力的做法,显然是每次修改单点颜 ...
- 【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序
[BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n n ...
- QTREE6 - Query on a tree VI 解题报告
QTREE6 - Query on a tree VI 题目描述 给你一棵\(n\)个点的树,编号\(1\)~\(n\).每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我 ...
- 【SPOJ】10628. Count on a tree(lca+主席树+dfs序)
http://www.spoj.com/problems/COT/ (速度很快,排到了rank6) 这题让我明白了人生T_T 我知道我为什么那么sb了. 调试一早上都在想人生. 唉. 太弱. 太弱. ...
- 【bzoj1803】Spoj1487 Query on a tree III DFS序+主席树
题目描述 You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node w ...
- 树链剖分【p4116】Qtree3 - Query on a tree
Description 给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白 有两种操作: 0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑) 1 v : 询问1到v的路径上的第一个黑 ...
- LCA【SP913】Qtree - Query on a tree II
Description 给定一棵n个点的树,边具有边权.要求作以下操作: DIST a b 询问点a至点b路径上的边权之和 KTH a b k 询问点a至点b有向路径上的第k个点的编号 有多组测试数据 ...
- SPOJ QTREE6 Query on a tree VI 树链剖分
题意: 给出一棵含有\(n(1 \leq n \leq 10^5)\)个节点的树,每个顶点只有两种颜色:黑色和白色. 一开始所有的点都是黑色,下面有两种共\(m(1 \leq n \leq 10^5) ...
随机推荐
- MT【202】内准圆
双曲线$\dfrac{x^2}{4}-\dfrac{y^2}{12}=1$ 的右焦点为 F,左准线为 L. 椭圆C 以F和L为其的焦点及准线,过F作一条斜率为 1 的直线交椭圆C于点A和B. 若椭圆C ...
- MT【178】平移不变性
(2008年北大自招)已知$a_1,a_2,a_3;b_1,b_2,b_3$满足$a_1+a_2+a_3=b_1+b_2+b_3$$a_1a_2+a_2a_3+a_3a_1=b_1b_2+b_2b_3 ...
- 在Mac上配置全局的Git忽略文件
现在同时搞着好几个项目,在Xcode.IDEA.Eclipse之间频繁的切换,每个项目的忽略文件列表都不一样,每个项目都有一个.gitignore,甚是麻烦,今天网上拔出来一个设置全局忽略的办法,记录 ...
- 40+ 个非常有用的 Oracle 查询语句
40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询.这些是所有 Oracle 开发者都必备的技能,所以快快收藏吧! 日期/时间 ...
- bzoj4542: [Hnoi2016]大数(莫队)
这题...离散化...$N$和$n$搞错了...查了$2h$...QAQ 考虑$s[l...r]$,可以由两个后缀$suf[l]-suf[r+1]$得到$s[l...r]$代表的数乘$10^k$得到的 ...
- 各种蕴含算法思想的DP - 2
study from: https://www.cnblogs.com/flashhu/p/9480669.html 3.斜率dp study from:http://www.cnblogs.com/ ...
- python常用模块-配置文档模块(configparser)
python常用模块-配置文档模块(configparser) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. ConfigParser模块用于生成和修改常见配置文档,当前模块的名称 ...
- logback常见配置
依赖jar包 <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core --> <dependency& ...
- spring框架学习(三)spring与junit整合测试
package cn.mf.b_test; import javax.annotation.Resource; import org.junit.Test; import org.junit.runn ...
- ASP.NET实现网站的自动升级
网站的自动升级主要是要实现从一台服务器上下载某些文件到本服务器上,然后对下载下来的文件进行更新等操作. 比如,现在有服务器A,服务器B和客户端C. 作为COM公司开发的产品DIV网站系统被安装到服务器 ...