题目传送门

题意:给你一棵树, 然后树上的点都有颜色,且原来为黑,现在有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. docker的基本安装和命令详解

    docker的安装 yum install docker-io docker的启动 /bin/systemctl start docker.service docker查找镜像 docker sear ...

  2. Web容器启动中执行某个Java类

    1.监听(Listener) <!-- 配置监听 --> <listener> <listener-class>com.xian.jdbc.GetPropertie ...

  3. Okhttp3 网络请求框架与 Gson

    Maven环境 : <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>o ...

  4. Usaco Training [1.3] wormhole

    传送门 解题要素:代码能力 解题步骤:理解题意 - >搜索枚举所有可能的配对情况 - >判断冲突并求解 - >调试 一. 理解题意 这里讲几个不容易理解的点: 1. +x方向 即向右 ...

  5. HBase MapReduce 一些 ClassNotFoundException 所缺少的jar包

    我们在用 java 操作 HBase  时,可能会出现相关的 ClassNotFoundException  等异常信息,但是我们又不想把 HBase lib 下的所有jar包全部导入到工程,因为会有 ...

  6. C#连接Oracle数据库字符串(引入DLL)

    需求:从一台Oracle数据库获取数据,本以为是很简单的事情,直接将原来的SqlClient换成OracleClient调用,结果远没自己想的简单.要么安装Oracle客户端,要么安装PLSQL.网上 ...

  7. C#使用WebClient调用接口

    用于上传图片base64位 private void upLoadCunzai() { errorstring += " upLoadCunzai方法执行成功:用于上传已经存在人员摄像头照片 ...

  8. Spring IoC源码解析之getBean

    一.实例化所有的非懒加载的单实例Bean 从org.springframework.context.support.AbstractApplicationContext#refresh方法开发,进入到 ...

  9. Unity进阶之:Shader渲染

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  10. JavaScript数据结构——队列的实现与应用

    队列与栈不同,它遵从先进先出(FIFO——First In First Out)原则,新添加的元素排在队列的尾部,元素只能从队列头部移除. 我们在前一篇文章中描述了如何用JavaScript来实现栈这 ...