题目传送门

题意:给你一棵树, 然后树上的点都有颜色,且原来为黑,现在有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 边分治的更多相关文章

  1. QTREE5 - Query on a tree V——LCT

    QTREE5 - Query on a tree V 动态点分治和动态边分治用Qtree4的做法即可. LCT: 换根后,求子树最浅的白点深度. 但是也可以不换根.类似平常换根的往上g,往下f的拼凑 ...

  2. 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 ...

  3. QTREE5 - Query on a tree V(LCT)

    题意翻译 你被给定一棵n个点的树,点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的边个数. 一开始所有的点都是黑色的. 要求作以下操作: 0 i 将点i的颜 ...

  4. SPOJ QTREE Query on a tree V ——动态点分治

    [题目分析] QTREE4的弱化版本 建立出分治树,每个节点的堆表示到改点的最近白点距离. 然后分治树上一直向上,取min即可. 正确性显然,不用担心出现在同一子树的情况(不会是最优解),请自行脑补. ...

  5. SPOJ QTREE4 - Query on a tree IV 树分治

    题意: 给出一棵边带权的树,初始树上所有节点都是白色. 有两种操作: C x,改变节点x的颜色,即白变黑,黑变白 A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为0). 分析: ...

  6. SPOJ - QTREE4 Query on a tree IV 边分治

    题目传送门 题意:有一棵数,每个节点有颜色,黑色或者白色,树边有边权,现在有2个操作,1修改某个点的颜色, 2询问2个白点的之前的路径权值最大和是多少. 题解: 边分治思路. 1.重构图. 因为边分治 ...

  7. SPOJ 375. Query on a tree (树链剖分)

    Query on a tree Time Limit: 5000ms Memory Limit: 262144KB   This problem will be judged on SPOJ. Ori ...

  8. 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 ...

  9. spoj 375 Query on a tree(树链剖分,线段树)

      Query on a tree Time Limit: 851MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Sub ...

随机推荐

  1. [Hei.Captcha] Asp.Net Core 跨平台验证码实现

    写在前面 说起来比较丢脸.我们有个手机的验证码发送逻辑需要使用验证码,这块本来项目里面就有验证码绘制逻辑,.Net Framework的,使用的包是System.Drawing,我把这验证码绘制逻辑复 ...

  2. 【Android】ViewModel+LiveData:更加直接地控制视图的方式

    目录 LiveData 前言 使用ViewModel+LiveData LiveData 前言   ViewModel通过将UI data保存在ViewModel类实例的内部,从而大大地将MVC中的 ...

  3. cogs 264. 数列操作 单点修改 区间查询

    http://cogs.pro:8080/cogs/problem/problem.php?pid=pyNimmVeq 264. 数列操作 ★☆   输入文件:shulie.in   输出文件:shu ...

  4. 自己学习并保存的一些shell命令

    摘要: 在学习过程中,不免会遇到有些命令,那种需要的,但是你没有掌握的命令.为了节省时间,担心忘记这些,特开辟这个随笔,随时记录用到的一些命令.那么常用的不提了,自己去收集吧~ 1.文件按日期排序 应 ...

  5. node获取本机动态IP,并对应修改相关JavaScript文件的IP地址

    目录 由于本机是自动获取分配的动态IP,所以每次重启后需要重新更改与IP相关文件 参考 时间:2018-08-02,更新时间:2018-11-06 注意:在win10环境运行无问题 由于本机是自动获取 ...

  6. 【java提高】(17)---Java 位运算符

    Java 位运算符 &.|.^.~.<<.>> 以前学过有关java的运算符,不过开发了这么久也很少用过这个.现在由于开发需要,所以现在再来回顾整理下有关java的运算 ...

  7. 聊一聊 SpringBoot 自动配置的原理

    解析思路 我们建立好一个SpringBoot的工程后,我们将从启动类,SpringBootApplication开始进行探究. 开始解析 首先我们建立一个 Springboot的工程.找到启动类,我们 ...

  8. Scrum Master如何让敏捷团队正常运转?

    官方<Scrum指南>中定义:Scrum Master在Scrum团队中属于服务型领导,负责践行和支持<Scrum指南>中定义的Scrum,要帮团队的每个人理解Scrum理论. ...

  9. Vue cli2.0 项目中使用Monaco Editor编辑器

    monaco-editor 是微软出的一条开源web在线编辑器支持多种语言,代码高亮,代码提示等功能,与Visual Studio Code 功能几乎相同. 在项目中可能会用带代码编辑功能,或者展示代 ...

  10. jsp和servlet开发过程中参数传递乱码问题总结

    1.前言 相信很多初学者在学习javaWeb基础知识时,总会遇到各种各样的乱码问题,我也是从那个时候过来的.当时遇到各种乱码问题,只能通过面向百度的方式,解决各种乱码问题,乱码虽然问题能解决,但是总是 ...