题目传送门

题意:有一棵数,每个节点有颜色,黑色或者白色,树边有边权,现在有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. 【JDK】JDK源码分析-AbstractQueuedSynchronizer(2)

    概述 前文「JDK源码分析-AbstractQueuedSynchronizer(1)」初步分析了 AQS,其中提到了 Node 节点的「独占模式」和「共享模式」,其实 AQS 也主要是围绕对这两种模 ...

  2. Serilog 自定义Enricher 来增加记录的信息

    Serilog 自定义Enricher 来增加记录的信息 Intro Serilog 是 .net 里面非常不错的记录日志的库,结构化日志记录,而且配置起来很方便,自定义扩展也很方便 Serilog ...

  3. pipreqs 生成requirements.txt文件时编码错误问题

    1,首先安装pipreqs --> pip install pipreqs 2.生成相应项目的路径  --> pipreqs  e:\a\b 在此时可能会遇见 UnicodeDecodeE ...

  4. leetcode 29 两数相除

    问题描述 给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor 得到的商. 示例 ...

  5. webgl核心要素

    WebGL是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,提供硬件3D加速渲染, ...

  6. 【POJ - 2236】Wireless Network (并查集)

    Wireless Network 这接翻译了 Descriptions 地震发生在东南亚.ACM(亚洲合作医疗团队)已经与膝上电脑建立了无线网络,但是一次意外的余震袭击,网络中的所有计算机都被打破了. ...

  7. 用xshell链接虚拟机上的linux

    [步骤]一.安装VMware直接点击下一步即可 二.安装linux下载CentOS,在VMware中安装,这个网上有很多教程,这里就不赘述了. 三.配置要想连接上xshell,需要配置IP,将Linu ...

  8. 使用bibtex为latex论文添加参考文献

    此文以引用Shannon的Prediction  and  Entropy  of Printed  English为例 1. bib文件 1.1 准备工作 进入Google Scholar 点击设置 ...

  9. HTTP与HTTPS之面试必备

    本文主要讲解Http与https的区别,以及https是怎样加密来保证安全的. 首先讲这俩个协议的简单区别: HTTP:超文本传输协议. HTTPS:安全套接字层超文本传输协议HTTP+SSL HTT ...

  10. C#读取Txt大数据并更新到数据库

    环境 Sqlserver 2016 .net 4.5.2 目前测试数据1300万 大约3-4分钟.(限制一次读取条数 和 线程数是 要节省服务器资源,如果调太大服务器其它应用可能就跑不了了), Sql ...