BZOJ 3991(dfs序 + LCA 公式推导)
来源:互联网 发布:狮子机平均分打法数据 编辑:程序博客网 时间:2024/06/07 00:20
题意:
给定一颗带权的树(n<=1e5),维护一个动态的集合(即插入点和删除点),求从其中一点出发到达所有点并返回的最小距离。
分析:
到达所有点并返回,是这些点用最少的边连起来的权值的2倍。这样只需动态计算,最少边的和。
这里以1为根节点,跑一遍dfs序。
考虑插入:那么如果插入点得dfs序,在集合中存在点dfs序的中间,找到比之小的最大点,和比之大的最小点,因为插入点在内部这两点连线与该点得距离最小。
否则,插入点在外部,找dfs序最大和最小点,即可。
删除是插入的逆操作。
//#pragma comment(linker, "/STACK:1024000000,1024000000")#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <set>#include <map>#include <string>#include <list>#include <cstdlib>#include <queue>#include <stack>#include <cmath>#include <bitset>#include <cassert>#define ALL(a) a.begin(), a.end()#define clr(a, x) memset(a, x, sizeof a)#define X first#define Y second#define pb push_back#define lowbit(x) (x&(-x))#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define rep1(i,x,y) for(int i=x;i<=y;i++)#define rep(i,n) for(int i=0;i<(int)n;i++)using namespace std;const double eps = 1e-10;typedef long long LL;typedef long long ll;typedef pair<int, int> pii;const int oo =0x3f3f3f3f;const int maxn=100000+100;const int DEG=30;struct Edge{ int v, nxt , cap;} edge[maxn<<1];int n, head[maxn], tot, fa[maxn][DEG], deg[maxn], sz[maxn];void init(){ clr(head, -1); tot=0;}void AddEdge(int u, int v ,int c){ edge[tot].v=v; edge[tot].cap=c; edge[tot].nxt=head[u]; head[u]=tot++;}void dfs(int u){ for(int i=1; i<DEG; i++) fa[u][i]=fa[fa[u][i-1]][i-1]; sz[u]=1; for(int i=head[u]; ~i; i=edge[i].nxt) { int v=edge[i].v; if(v==fa[u][0])continue ; deg[v]=deg[u]+1; fa[v][0]=u; dfs(v); sz[u]+=sz[v]; }}int par(int u, int det){ for(int i=0; det; det>>=1, i++) if(det&1) u=fa[u][i]; return u;}int LCA(int u, int v){ if(deg[u]>deg[v])swap(u, v); int tu=u, tv=v; tv=par(v, deg[v]-deg[u]); if(tu==tv)return tu; for(int i=DEG-1; i>=0; i--) { if(fa[tu][i]==fa[tv][i])continue ; tu=fa[tu][i], tv=fa[tv][i]; } return fa[tu][0];}int id[maxn] , cnt_=0 ;ll d[maxn];void init_dfs(int u,int f , ll len){ id[u] = ++cnt_; d[u] = len; for(int i=head[u]; ~i; i=edge[i].nxt) { int v=edge[i].v; if(v==f)continue ; init_dfs(v,u,len+edge[i].cap); }}struct node{ int id,u; node(int u=0,int id=0):u(u),id(id) {} bool operator<(const node& rhs)const { return id < rhs.id; }};set<node> que;typedef set<node>::iterator set_p;ll now = 0;void cal(int u){ if(que.empty()) { que.insert(node(u,id[u])); return ; } set_p p = que.find(node(u,id[u])) , p1, p2; int flag = -1; if(p == que.end()) { que.insert(node(u,id[u])); flag = 1; } p = que.find(node(u,id[u])); p1 = p2 = p; set_p ed = que.end(); --ed; if(p == que.begin()) p1++,p2=ed; else if(p == ed) p1=que.begin(),p2=ed,--p2; else p1--, p2++; int y = p2->u; int x = p1->u; now+=((ll)d[u]-d[LCA(x,u)]-d[LCA(y,u)]+d[LCA(x,y)])*flag; if(flag == -1) que.erase(p);}int Q;int main(){ scanf("%d %d", &n ,&Q); init(); for(int i=0; i<n-1; i++) { int u, v , c; scanf("%d%d%d", &u, &v,&c); AddEdge(u, v , c); AddEdge(v, u , c); } deg[1]=0; fa[1][0]=1; dfs(1); cnt_ = 0; d[1] = 0; init_dfs(1,-1,0); que.clear(); now = 0; while(Q--) { int u; scanf("%d",&u); cal(u); printf("%lld\n",now*2); }}
0 0
- BZOJ 3991(dfs序 + LCA 公式推导)
- BZOJ 3991 SDOI 2015 寻宝游戏(异象石) LCA + Set + DFS序
- bzoj 3991: [SDOI2015]寻宝游戏 (set+LCA+dfs序+虚树)
- [LCA][dfs序]BZOJ 2819: Nim
- bzoj 1426(期望dp)(公式推导)
- bzoj 2754: [SCOI2012]喵星球上的点名 (fail树+树状数组+lca+dfs序)
- BZOJ 2819 Nim 树链剖分/DFS序+LCA+树状数组
- 【BZOJ 3306】树【LCA、DFS序、线段树】
- BZOJ 2819: Nim 树状数组+lca+dfs序
- BZOJ 2956 模积和 公式推导
- [BZOJ]3727 Final Zadanie 公式推导
- Wannafly挑战赛6 A(二分)B(dfs)C(公式推导)E(技巧)
- poj3417Network(LCA+dfs)
- hdu5452(LCA+DFS)
- bzoj 1787(LCA)
- Catalan公式推导(转载)
- 坐标旋转公式(推导)
- 公式推导
- 关于iOS9 更新后,微博,微信 语言变成英语的问题
- Java中ClassPath的作用
- ubuntu openjdk-8-*安装和版本更新
- 领域驱动设计之领域模型
- spark core源码分析17 RDD相关API
- BZOJ 3991(dfs序 + LCA 公式推导)
- 多态
- 查询手机联系人和sim卡联系人
- JavaScript性能优化
- jQuery之简单的表单验证
- 招聘一个靠谱的 iOS
- 栈的应用-迷宫问题-数据结构
- IT成长路<2014.9-2015.3>"不惑"下篇
- OperationalError: (1130, "Host ... not allowed to connect this MySQL server")