题目传送门

题意:有一棵数,每个节点有颜色,黑色或者白色,树边有边权,现在有2个操作,1修改某个点的颜色, 2询问2个白点的之前的路径权值最大和是多少。

题解:

边分治思路。

1.重构图。 因为边分治在菊花图的情况下情况不理想,所以需要先把图重新构建一下,是每个点的度数不超过3。

2.找在新图里面  一条边使得 断开这条边的情况下,左右2新树使得较大的那个子树是所有情况下的最小值。

3.开2个优先队列去维护左边新树的白点的最大值, 右边新树的所有白点的最大值, 然后 左边白点+右边白点+中间边就是最大值。

4.对于2个新图都执行 2-3的操作。

代码:

 #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]; int to[N<<];
int ct[N<<]; int nt[N<<];
int tot;
void init(){
tot = ;
memset(head, -, sizeof(head));
return ;
};
void add(int u, int v, int val){
to[tot] = v; ct[tot] = val;
nt[tot] = head[u]; head[u] = tot++;
return ;
}
}e[];
int n, u, v, w;
void rebuild(int o, int u){
int ff = ;
for(int i = e[].head[u]; ~i; i = e[].nt[i]){
v = e[].to[i], w = e[].ct[i];
if(v == o) continue;
if(!ff){
e[].add(u, v, w);
e[].add(v, u, w);
ff = u;
}
else {
++n;
e[].add(ff, n, );
e[].add(n, ff, );
e[].add(v, n, w);
e[].add(n, v, w);
ff = n;
}
rebuild(u, v);
}
return ;
}
vector<pll> vc[N];
priority_queue<pll> pq[N<<][]; int wedge[N<<];
int white[N], sz[N];
int cut[N<<];
int id, maxnum = ;
void get_edge(int o, int u, int num){
sz[u] = ;
int tmp = ;
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];
tmp = max(num-sz[v], sz[v]);
if(tmp < maxnum){
id = i;
maxnum = tmp;
}
}
return ;
}
int k = , op;
void dfs(int o, int u, int w){
sz[u] = ;
if(white[u]){
pq[k][op].push(pll(w, u));
if(op == ) vc[u].push_back(pll(-k, w));
else vc[u].push_back(pll(k, w));
}
for(int i = e[].head[u]; ~i; i = e[].nt[i]){
int v = e[].to[i];
if(v == o || cut[i>>]) continue;
dfs(u, v, w+e[].ct[i]);
sz[u] += sz[v];
}
return ;
}
int ans[N], lch[N], rch[N];
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();
if(pq[k][].empty() || pq[k][].empty())
ans[k] = ;
else {
int val1 = pq[k][].top().fi, val2 = pq[k][].top().fi;
int sum = val1 + val2 + wedge[k];
ans[k] = max(sum, );
}
if(lch[k]) ans[k] = max(ans[k], ans[lch[k]]);
if(rch[k]) ans[k] = max(ans[k], ans[rch[k]]);
return ;
}
int solve(int u, int num){
if(num == ) return ;
maxnum = inf;
get_edge(, u, num);
int now = ++k, nid = id;
cut[nid >> ] = ;
wedge[k] = e[].ct[nid];
op = ;
dfs(, e[].to[nid], );
op = ;
dfs(, e[].to[nid^], );
lch[now] = solve(e[].to[nid], sz[e[].to[nid]]);
rch[now] = solve(e[].to[nid^], sz[e[].to[nid^]]);
update(now);
return now;
}
void setWhite(int u){
for(int i = vc[u].size()-; i >= ; --i){
pll tmp = vc[u][i];
int k = tmp.fi, ct = tmp.se;
if(k < ) pq[-k][].push(pll(ct, u));
else pq[k][].push(pll(ct, u));
update(abs(k));
}
return ;
}
void setBlack(int u){
for(int i = vc[u].size()-; i >= ; --i)
update(abs(vc[u][i].fi));
return ;
}
int main(){
scanf("%d", &n);
int white_num = n, q;
char op[];
e[].init(); e[].init();
for(int i = ; i < n; i++){
scanf("%d%d%d", &u, &v, &w);
e[].add(u, v, w);
e[].add(v, u, w);
white[i] = ;
}
white[n] = ;
rebuild(, );
solve(, n);
scanf("%d", &q);
while(q--){
scanf("%s", op);
if(op[] == 'A') {
if(white_num == ) puts("They have disappeared.");
else if(white_num == ) puts("");
else printf("%d\n", ans[]);
}
else {
scanf("%d", &u);
white[u] ^= ;
if(white[u])
setWhite(u), ++white_num;
else
setBlack(u), --white_num;
}
}
return ;
}
 #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]; int to[N<<];
int ct[N<<]; int nt[N<<];
int tot;
void init(){
tot = ;
memset(head, -, sizeof(head));
return ;
};
void add(int u, int v, int val){
to[tot] = v; ct[tot] = val;
nt[tot] = head[u]; head[u] = tot++;
return ;
}
}e[];
int n, u, v, w;
void rebuild(int o, int u){
int ff = ;
for(int i = e[].head[u]; ~i; i = e[].nt[i]){
v = e[].to[i], w = e[].ct[i];
if(v == o) continue;
if(!ff){
e[].add(u, v, w);
e[].add(v, u, w);
ff = u;
}
else {
++n;
e[].add(ff, n, );
e[].add(n, ff, );
e[].add(v, n, w);
e[].add(n, v, w);
ff = n;
}
rebuild(u, v);
}
return ;
}
vector<pll> vc[N];
priority_queue<pll> pq[N<<][]; int wedge[N<<];
int white[N], sz[N];
int cut[N<<];
int id, maxnum = ;
void get_edge(int o, int u, int num){
sz[u] = ;
int tmp = ;
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];
tmp = max(num-sz[v], sz[v]);
if(tmp < maxnum){
id = i;
maxnum = tmp;
}
}
return ;
}
int k = , op;
void dfs(int o, int u, int w){
sz[u] = ;
if(white[u]){
pq[k][op].push(pll(w, u));
if(op == ) vc[u].push_back(pll(-k, w));
else vc[u].push_back(pll(k, w));
}
for(int i = e[].head[u]; ~i; i = e[].nt[i]){
int v = e[].to[i];
if(v == o || cut[i>>]) continue;
dfs(u, v, w+e[].ct[i]);
sz[u] += sz[v];
}
return ;
}
int ans[N], lch[N], rch[N];
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();
if(pq[k][].empty() || pq[k][].empty())
ans[k] = ;
else {
int val1 = pq[k][].top().fi, val2 = pq[k][].top().fi;
int sum = val1 + val2 + wedge[k];
ans[k] = max(sum, );
}
if(lch[k]) ans[k] = max(ans[k], ans[lch[k]]);
if(rch[k]) ans[k] = max(ans[k], ans[rch[k]]);
return ;
}
int solve(int u, int num){
if(num == ) return ;
maxnum = inf;
get_edge(, u, num);
int now = ++k, nid = id;
cut[nid >> ] = ;
wedge[k] = e[].ct[nid];
op = ;
dfs(, e[].to[nid], );
op = ;
dfs(, e[].to[nid^], );
lch[now] = solve(e[].to[nid], sz[e[].to[nid]]);
rch[now] = solve(e[].to[nid^], sz[e[].to[nid^]]);
update(now);
return now;
}
void setWhite(int u){
for(int i = vc[u].size()-; i >= ; --i){
pll tmp = vc[u][i];
int k = tmp.fi, ct = tmp.se;
if(k < ) pq[-k][].push(pll(ct, u));
else pq[k][].push(pll(ct, u));
update(abs(k));
}
return ;
}
void setBlack(int u){
for(int i = vc[u].size()-; i >= ; --i)
update(abs(vc[u][i].fi));
return ;
}
int main(){
scanf("%d", &n);
int white_num = n, q;
char op[];
e[].init(); e[].init();
for(int i = ; i < n; i++){
scanf("%d%d%d", &u, &v, &w);
e[].add(u, v, w);
e[].add(v, u, w);
white[i] = ;
}
white[n] = ;
rebuild(, );
solve(, n);
scanf("%d", &q);
while(q--){
scanf("%s", op);
if(op[] == 'A') {
if(white_num == ) puts("They have disappeared.");
else if(white_num == ) puts("");
else printf("%d\n", ans[]);
}
else {
scanf("%d", &u);
white[u] ^= ;
if(white[u])
setWhite(u), ++white_num;
else
setBlack(u), --white_num;
}
}
return ;
}

SPOJ - QTREE4 Query on a tree IV 边分治的更多相关文章

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

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

  2. SPOJ QTREE4 - Query on a tree IV

    You are given a tree (an acyclic undirected connected graph) with N nodes, and nodes numbered 1,2,3. ...

  3. SPOJ QTREE4 Query on a tree IV ——动态点分治

    [题目分析] 同bzoj1095 然后WA掉了. 发现有负权边,只好把rmq的方式改掉. 然后T了. 需要进行底(ka)层(chang)优(shu)化. 然后还是T 下午又交就A了. [代码] #in ...

  4. 洛谷 P2056 [ZJOI2007]捉迷藏 || bzoj 1095: [ZJOI2007]Hide 捉迷藏 || 洛谷 P4115 Qtree4 || SP2666 QTREE4 - Query on a tree IV

    意识到一点:在进行点分治时,每一个点都会作为某一级重心出现,且任意一点只作为重心恰好一次.因此原树上任意一个节点都会出现在点分树上,且是恰好一次 https://www.cnblogs.com/zzq ...

  5. SP2666 QTREE4 - Query on a tree IV(LCT)

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

  6. SPOJ - QTREE5 Query on a tree V 边分治

    题目传送门 题意:给你一棵树, 然后树上的点都有颜色,且原来为黑,现在有2个操作,1 改变某个点的颜色, 2 询问树上的白点到u点的最短距离是多少. 题解: 这里用的还是边分治的方法. 把所有东西都抠 ...

  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. QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树

    Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...

随机推荐

  1. .NET读写DBF

    C# 读写DBF分为两种模式,一种为OLEDB驱动,需要安装一个文件“VFPOLEDBSetup.msi”: 一种为Odbc模式,这种几乎上不需要安装Odbc驱动 我这边用的是第一种. /// < ...

  2. Core CLR Host 源码简单分析

    在定制 CLR Host的时候,可以通过调用如下代码,来获取当前需要被宿主的程序调用入口: hr = Host->CreateDelegate( domainId, L"Main,Ve ...

  3. 自定义SWT控件七之自定义Shell(可伸缩窗口)

    7.可伸缩窗口 该自定义窗口可以通过鼠标随意更改窗口大小 package com.hikvision.encapsulate.view.control.shell; import org.eclips ...

  4. 邮件服务配置(虚拟域&虚拟用户)

    邮件服务配置(虚拟域&虚拟用户) 现在我做的是: Linux + httpd + php + mariadb + postfix + dovecot + phpMyAdmin + postfi ...

  5. abc -- 牛客

    题目描述 设a.b.c均是0到9之间的数字,abc.bcc是两个三位数,且有:abc+bcc=532.求满足条件的所有a.b.c的值. 输入描述: 题目没有任何输入. 输出描述: 请输出所有满足题目条 ...

  6. 单机版ZooKeeper的安装教程

    之前一直没有时间去整理,现在抽出几分钟时间整理以下,有问题的在评论区留言即可. 前期准备JDK环境(ZK需要jdk进行编译,本文以jdk1.8.0_211为例).Linux系统(本文以Centos7为 ...

  7. 从SpringBoot构建十万博文聊聊缓存穿透

    前言 在博客系统中,为了提升响应速度,加入了 Redis 缓存,把文章主键 ID 作为 key 值去缓存查询,如果不存在对应的 value,就去数据库中查找 .这个时候,如果请求的并发量很大,就会对后 ...

  8. springboot整合websocket原生版

    目录 HTTP缺点 HTTP websocket区别 websocket原理 使用场景 springboot整合websocket 环境准备 客户端连接 加入战队 微信公众号 主题 HTTP请求用于我 ...

  9. element ui 退出功能

    <template> <el-container class="home-wrapper"> <el-header> <el-row ty ...

  10. spark源码阅读---Utils.getCallSite

    1 作用 当该方法在spark内部代码中调用时,会返回当前调用spark代码的用户类的名称,以及其所调用的spark方法.所谓用户类,就是我们这些用户使用spark api的类. 2 内部实现 2.1 ...