SPOJ - QTREE4 Query on a tree IV 边分治
题意:有一棵数,每个节点有颜色,黑色或者白色,树边有边权,现在有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 边分治的更多相关文章
- SPOJ QTREE4 - Query on a tree IV 树分治
题意: 给出一棵边带权的树,初始树上所有节点都是白色. 有两种操作: C x,改变节点x的颜色,即白变黑,黑变白 A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为0). 分析: ...
- 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. ...
- SPOJ QTREE4 Query on a tree IV ——动态点分治
[题目分析] 同bzoj1095 然后WA掉了. 发现有负权边,只好把rmq的方式改掉. 然后T了. 需要进行底(ka)层(chang)优(shu)化. 然后还是T 下午又交就A了. [代码] #in ...
- 洛谷 P2056 [ZJOI2007]捉迷藏 || bzoj 1095: [ZJOI2007]Hide 捉迷藏 || 洛谷 P4115 Qtree4 || SP2666 QTREE4 - Query on a tree IV
意识到一点:在进行点分治时,每一个点都会作为某一级重心出现,且任意一点只作为重心恰好一次.因此原树上任意一个节点都会出现在点分树上,且是恰好一次 https://www.cnblogs.com/zzq ...
- SP2666 QTREE4 - Query on a tree IV(LCT)
题意翻译 你被给定一棵n个点的带边权的树(边权可以为负),点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的权值之和. 一开始所有的点都是白色的. 要求作以下 ...
- SPOJ - QTREE5 Query on a tree V 边分治
题目传送门 题意:给你一棵树, 然后树上的点都有颜色,且原来为黑,现在有2个操作,1 改变某个点的颜色, 2 询问树上的白点到u点的最短距离是多少. 题解: 这里用的还是边分治的方法. 把所有东西都抠 ...
- SPOJ 375. Query on a tree (树链剖分)
Query on a tree Time Limit: 5000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Ori ...
- 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 ...
- QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树
Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...
随机推荐
- 【JDK】JDK源码分析-AbstractQueuedSynchronizer(2)
概述 前文「JDK源码分析-AbstractQueuedSynchronizer(1)」初步分析了 AQS,其中提到了 Node 节点的「独占模式」和「共享模式」,其实 AQS 也主要是围绕对这两种模 ...
- Serilog 自定义Enricher 来增加记录的信息
Serilog 自定义Enricher 来增加记录的信息 Intro Serilog 是 .net 里面非常不错的记录日志的库,结构化日志记录,而且配置起来很方便,自定义扩展也很方便 Serilog ...
- pipreqs 生成requirements.txt文件时编码错误问题
1,首先安装pipreqs --> pip install pipreqs 2.生成相应项目的路径 --> pipreqs e:\a\b 在此时可能会遇见 UnicodeDecodeE ...
- leetcode 29 两数相除
问题描述 给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor 得到的商. 示例 ...
- webgl核心要素
WebGL是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,提供硬件3D加速渲染, ...
- 【POJ - 2236】Wireless Network (并查集)
Wireless Network 这接翻译了 Descriptions 地震发生在东南亚.ACM(亚洲合作医疗团队)已经与膝上电脑建立了无线网络,但是一次意外的余震袭击,网络中的所有计算机都被打破了. ...
- 用xshell链接虚拟机上的linux
[步骤]一.安装VMware直接点击下一步即可 二.安装linux下载CentOS,在VMware中安装,这个网上有很多教程,这里就不赘述了. 三.配置要想连接上xshell,需要配置IP,将Linu ...
- 使用bibtex为latex论文添加参考文献
此文以引用Shannon的Prediction and Entropy of Printed English为例 1. bib文件 1.1 准备工作 进入Google Scholar 点击设置 ...
- HTTP与HTTPS之面试必备
本文主要讲解Http与https的区别,以及https是怎样加密来保证安全的. 首先讲这俩个协议的简单区别: HTTP:超文本传输协议. HTTPS:安全套接字层超文本传输协议HTTP+SSL HTT ...
- C#读取Txt大数据并更新到数据库
环境 Sqlserver 2016 .net 4.5.2 目前测试数据1300万 大约3-4分钟.(限制一次读取条数 和 线程数是 要节省服务器资源,如果调太大服务器其它应用可能就跑不了了), Sql ...