题目传送门

题意:给你一棵树, 然后树上的点都有颜色,且原来为黑,现在有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. 【Android Studio】常用快捷键

    1. 删除一行:Ctrl + X 更新中……

  2. MapReduce 运行全过程解析

    关注公众号,大家可以在公众号后台回复“博客园”,免费获得作者 Java 知识体系/面试必看资料. 前言 前面我们讲了 MapReduce 的编程模型,我们知道他主要分成两大阶段来完成一项任务,一是 m ...

  3. 关于程序null值的见解

    今天遇到了一个问题,查询一条数据,返回用list接,发现少了2个值(ssh框架).执行SQL少的这两个字段的值为null.上图说明一下: 可以看到第一次查询没有角标38.39的值. 是同一条SQL,第 ...

  4. 运营商手机视频流量包业务日志ETL及统计分析

    自己做过的项目在这里做一个记录,否则就感觉不是自己的了.一是因为过去时间已经很长了,二是因为当时做得有点粗糙,最后还不了了之了. 话不多说,先大致介绍一下项目背景.以前各大手机视频 App 一般都有运 ...

  5. .net持续集成测试篇之Nunit参数化测试

    系列目录 在进行单元测试的时候,很多时候,很多时候我们都是在单元测试方法内部提供特定的值,但是这样测试往往造成样本数不足从而导致覆盖的结果不够全面,很多时候我们更想提供来自外部的,满足条件的一组值来进 ...

  6. 定制开发kubernetes流程

    kubernetes集群三步安装 概述 本文介绍如何对kubernetes进行二次开发,仓库如何管理,git分支如何管理,怎样利用CI去编译与发布以及如何给社区贡献代码等,结合实际例子,望对大家有所帮 ...

  7. 数据结构之队列java版

    //java由于泛型的擦除,用起来十分不方便 abstract class BaseQueue<T>{ abstract boolean enQueue(T x); abstract T ...

  8. 如何获取app中的toast

    前言 Toast是什么呢?在这个手机飞速发展的时代,app的种类也越来越多,那们在日常生活使用中,经常会发现,当你在某个app的输入框输入非法字符或者非法执行某个流程时,经常看到系统会给你弹出一个黑色 ...

  9. 28岁,转行学 IT 靠谱吗?

    前几天在知乎上,刷到这么一个问题 鉴于有不少人看了我的blog给我私信一些职业规划相关的问题,讨论很多的就是担心自己年龄是否还适合转行. 于是决定静心下来码了一篇回答, 同时搬到博客园来供大家消遣.. ...

  10. Streaming+Sparksql使用sql实时分析 rabbitmq+mongodb+hive

    SparkConf sparkConf = new SparkConf()//此处使用一个链接切记使用一个链接否则汇报有多个sparkcontext错误 .setAppName("Spark ...