SPOJ - QTREE5 Query on a tree V 边分治
题意:给你一棵树, 然后树上的点都有颜色,且原来为黑,现在有2个操作,1 改变某个点的颜色, 2 询问树上的白点到u点的最短距离是多少。
题解:
这里用的还是边分治的方法。
把所有东西都抠出来, 然后每次询问的时候都访问每幅分割图的另外一侧。
代码:
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = (int)1e9+;
const int N = 2e5 + ;
struct Node{
int head[N], to[N<<], nt[N<<], ct[N<<];
int tot;
void init(){
memset(head, -, sizeof(head));
tot = ;
}
void add(int u, int v, int cost){
ct[tot] = cost;
to[tot] = v;
nt[tot] = head[u];
head[u] = tot++;
}
}e[];
int n, m, white[N], cut[N<<];
void rebuild(int o, int u){
int ff = ;
for(int i = e[].head[u]; ~i; i = e[].nt[i]){
int v = e[].to[i];
if(o == v) continue;
if(!ff){
e[].add(u, v, );
e[].add(v, u, );
ff = u;
}
else {
++n;
e[].add(ff, n, ); e[].add(n, ff, );
e[].add(n, v, ); e[].add(v, n, );
ff = n;
}
rebuild(u, v);
}
}
int sz[N], minval, id;
void get_edge(int o, int u, int num){
sz[u] = ;
for(int i = e[].head[u]; ~i; i = e[].nt[i]){
int v = e[].to[i];
if(v == o || cut[i>>]) continue;
get_edge(u, v, num);
sz[u] += sz[v];
int tmp = max(sz[v], num - sz[v]);
if(tmp < minval){
minval = tmp;
id = i;
}
}
}
int k = , op;
vector<pll> vc[N];
priority_queue<pll, vector<pll>, greater<pll> > pq[N<<][];
int wedge[N<<];
int mm;
void dfs2(int o, int u, int w){
vc[u].pb(pll(k*op, w));
sz[u] = ;
for(int i = e[].head[u]; ~i; i = e[].nt[i]){
int v = e[].to[i];
if(v == o || cut[i>>]) continue;
dfs2(u, v, w + e[].ct[i]);
sz[u] += sz[v];
}
}
void solve(int u, int num){
if(num <= ) return ;
minval = inf;
get_edge(, u, num);
int nid = id;
cut[nid>>] = ;
++k;
op = ;
dfs2(, e[].to[nid], );
op = -;
dfs2(, e[].to[nid^], );
wedge[k] = e[].ct[nid];
solve(e[].to[nid], sz[e[].to[nid]]);
solve(e[].to[nid^], sz[e[].to[nid^]]);
}
void Update(int k){
while(!pq[k][].empty() && !white[pq[k][].top().se]) pq[k][].pop();
while(!pq[k][].empty() && !white[pq[k][].top().se]) pq[k][].pop();
}
void setwhite(int u){
for(int i = ; i < vc[u].size(); i++){
int k = vc[u][i].fi, w = vc[u][i].se;
if(k < ) pq[-k][].push(pll(w,u));
else pq[k][].push(pll(w,u));
Update(abs(k));
}
}
void setblack(int u){
for(int i = ; i < vc[u].size(); i++){
int k = vc[u][i].fi;
Update(abs(k));
}
}
int Find(int u){
int ret = inf;
for(int i = ; i < vc[u].size(); i++){
int k = vc[u][i].fi, w = vc[u][i].se;
if(k < && !pq[-k][].empty())
ret = min(ret, w+wedge[-k]+pq[-k][].top().fi);
if(k > && !pq[k][].empty())
ret = min(ret, w+wedge[k]+pq[k][].top().fi);
}
return ret;
}
int main(){
e[].init(); e[].init();
scanf("%d", &n);
int u, v;
for(int i = ; i < n; i++){
scanf("%d%d", &u, &v);
e[].add(u, v, ); e[].add(v, u, );
}
memset(white, , sizeof(white));
rebuild(, );
solve(, n);
int num = , op;
scanf("%d", &m);
while(m--){
scanf("%d%d", &op, &v);
if(op == ){
white[v] ^= ;
if(white[v]){
setwhite(v);
num++;
}
else {
setblack(v);
num--;
}
}
else {
if(num == ) puts("-1");
else if(white[v]) puts("");
else {
printf("%d\n", Find(v));
}
}
}
return ;
}
SPOJ - QTREE5 Query on a tree V 边分治的更多相关文章
- QTREE5 - Query on a tree V——LCT
QTREE5 - Query on a tree V 动态点分治和动态边分治用Qtree4的做法即可. LCT: 换根后,求子树最浅的白点深度. 但是也可以不换根.类似平常换根的往上g,往下f的拼凑 ...
- SPOJ QTREE Query on a tree V
You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are number ...
- QTREE5 - Query on a tree V(LCT)
题意翻译 你被给定一棵n个点的树,点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的边个数. 一开始所有的点都是黑色的. 要求作以下操作: 0 i 将点i的颜 ...
- SPOJ QTREE Query on a tree V ——动态点分治
[题目分析] QTREE4的弱化版本 建立出分治树,每个节点的堆表示到改点的最近白点距离. 然后分治树上一直向上,取min即可. 正确性显然,不用担心出现在同一子树的情况(不会是最优解),请自行脑补. ...
- SPOJ QTREE4 - Query on a tree IV 树分治
题意: 给出一棵边带权的树,初始树上所有节点都是白色. 有两种操作: C x,改变节点x的颜色,即白变黑,黑变白 A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为0). 分析: ...
- SPOJ - QTREE4 Query on a tree IV 边分治
题目传送门 题意:有一棵数,每个节点有颜色,黑色或者白色,树边有边权,现在有2个操作,1修改某个点的颜色, 2询问2个白点的之前的路径权值最大和是多少. 题解: 边分治思路. 1.重构图. 因为边分治 ...
- SPOJ 375. Query on a tree (树链剖分)
Query on a tree Time Limit: 5000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Ori ...
- SPOJ QTREE Query on a tree 树链剖分+线段树
题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...
- spoj 375 Query on a tree(树链剖分,线段树)
Query on a tree Time Limit: 851MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Sub ...
随机推荐
- MyBatis框架之关联查询
概述:关联查询主要在<resultMap>元素中,用<association>配置一对一.用<collection> 配置一对多 一.一对一查询 1.使 ...
- codeforces 371A K-Periodic Array
很简单,就是找第i位.i+k位.i+2*k位...........i+m*k位有多少个数字,计算出每个数出现的次数,找到出现最多的数,那么K-Periodic的第K位数肯定是这个了.这样的话需要替换的 ...
- OI/ACM最全卡常大招
NO.10: 循环展开: 在缓存和寄存器允许的情况下一条语句内大量的展开运算会刺激 CPU 并发(蛤?这是个什么原理,算了,反正写了没坏处就这么写吧) NO.9: 特殊运算优化:(或许这真的没用) 取 ...
- 一文带你彻底理解 JavaScript 原型对象
一.什么是原型 原型是Javascript中的继承的基础,JavaScript的继承就是基于原型的继承. 1.1 函数的原型对象 在JavaScript中,我们创建一个函数A(就是声明一个函数), 那 ...
- Drawable 使用详解
极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android Drawable 是Android 中图像显示的常用方法. 概念:Drawable ...
- Spring cloud 超时配置总结
基准配置: eureka-server : 注册中心 端口号1000 service-A : 服务A端口号2000 service-B : 服务B 端口号3000 其中,B服务通过feign调用服务A ...
- SpringBoot操作ES进行各种高级查询
SpringBoot整合ES 创建SpringBoot项目,导入 ES 6.2.1 的 RestClient 依赖和 ES 依赖.在项目中直接引用 es-starter 的话会报容器初始化异常错误,导 ...
- c# 20160721
ctrl y =>反撤销 ctrl m m 隐藏当前代码段 重载运算符语法 把事件处理程序注册为 click事件的监听程序 [newButton.click+=newButton_click] ...
- WIN10家庭版桌面右键单击显示设置出现ms-settings:display或ms-settings:personalization-background解决办法[原创]
最近,笔者的笔记本卸载oracle数据库,注册表里面删除了不少相关信息,没想到担心的事情还是来了!桌面右键单击显示设置出现ms-settings:display或ms-settings:persona ...
- 从零写一个编译器(十三):代码生成之遍历AST
项目的完整代码在 C2j-Compiler 前言 在上一篇完成对JVM指令的生成,下面就可以真正进入代码生成部分了.通常现代编译器都是先把生成IR,再经过代码优化等等,最后才编译成目标平台代码.但是时 ...