HDU5296
来源:互联网 发布:杀手 知乎 编辑:程序博客网 时间:2024/05/18 18:18
首先dfs一个顺序,加一个节点u,如果u节点的dfs序,在集合中节点的dfs序之间,那么找到最接近的(u的dfs序)的两个数为x和y;
如果u节点的dfs序在集合中节点的dfs序的一侧,那么x和y为集合中dfs序的最大值和最小值,这样带入公式中求的就是添加这个节点所带来的需要添加的距离,
删除一个节点和添加时一样的。
假设节点要连接到一个链中,链的定点(x,y),那么
u连接到x的距离是dfn[u] + dfn[x] - 2dfn[ lca(u,x) ] ;
u连接到y的距离dfn[u] + dfn[y] - 2dfn[ lca(u,y) ] :
x连接到y的距离dfn[x] + dfn[y] - 2dfn[ lca(x,y) ] :
u连接到x-y这个链的距离 = (u到y+u到x-x到y)/2=dfn[u] - dfn[ lca(x,u) ] - dfn[ lca(y,u) ] + dfn[ lca(x,y) ]
#include<iostream>
#pragma warning(disable:4996)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<time.h>
#include<string>
#define cl(a,b) memset(a,b,sizeof(a))
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define REP(i,n) for(int i=0;i<n;++i)
#define REP1(i,a,b) for(int i=a;i<=b;++i)
#define REP2(i,a,b) for(int i=a;i>=b;--i)
#define MP make_pair
#define LL long long
#define ULL unsigned long long
#define X first
#define Y second
#define MAXN 100050
using namespace std;
vector<int> e[MAXN], c[MAXN];//边、权
set<int> st;
int fa[MAXN][20];//fa[i][j]就代表第i个结点的2^j级祖先
int p[MAXN];//p[i]就代表i点的dfs序是p[i]
int dfn[MAXN];//dfn[i]表示dfs序为i的结点是哪个
int dis[MAXN];//与根1的距离
int cid;//cid就是用来计数表示dfs序
int d[MAXN];//d[i]就是代表i点的深度
void dfs(int cur, int f) {
dfn[++cid] = cur;
p[cur] = cid;
for (int i = 1; i < 20; ++i)
fa[cur][i] = fa[fa[cur][i - 1]][i - 1];
for (int i = 0; i < e[cur].size(); ++i) {
int u = e[cur][i];
if (u == f)
continue;
d[u] = d[cur] + 1;
dis[u] = dis[cur] + c[cur][i];
fa[u][0] = cur;
dfs(u, cur);
}
}
//LCA求最近公共祖先
int lca(int u, int v) {
if (d[u] < d[v])
swap(u, v);
for (int i = 19; i >= 0; --i) {
if (d[fa[u][i]] >= d[v])
u = fa[u][i];
if (u == v)
return u;
}
for (int i = 19; i >= 0; --i) {
if (fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
}
int add(int u) {
if (st.empty())
return 0;
int x, y;
set<int>::iterator it = st.lower_bound(p[u]), itx = it;
itx--;
if (it == st.end() || it == st.begin()) {
it = st.begin();
itx = st.end();
itx--;
}
y = (*it);
x = (*itx);
y = dfn[y];
x = dfn[x];
return dis[u] - dis[lca(x, u)] - dis[lca(y, u)] + dis[lca(x, y)];
}
bool bo[MAXN];//是否在集合中
int main() {
int tt, ri = 0;
scanf("%d", &tt);
while (tt--) {
int n, q;
st.clear();
cid = 0;
scanf("%d%d", &n, &q);
for (int i = 0; i <= n; ++i)
{
bo[i] = false;
e[i].clear();
c[i].clear();
}
for (int i = 1; i < n; ++i) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
e[x].push_back(y);
c[x].push_back(z);
e[y].push_back(x);
c[y].push_back(z);
}
fa[1][0] = 1;
d[1] = 1;
dis[1] = 0;
dfs(1, -1);
int sum = 0;
printf("Case #%d:\n", ++ri);
for (int i = 1; i <= q; ++i) {
int x, y;
scanf("%d%d", &x, &y);
int tmp;
if (x == 1) {
if (!bo[y]){
bo[y] = true;
if (st.size() == 0) {
st.insert(p[y]);
}
else {
tmp = add(y);
st.insert(p[y]);
sum += tmp;
}
}
}
else {
if (bo[y]){
bo[y] = false;
st.erase(p[y]);
if (!st.empty()) {
sum -= add(y);
}
}
}
printf("%d\n", sum);
// printf("%d %d %d %d\n",now,i,sum,add(i));
}
}
return 0;
}
/*
6 5
1 2 2
1 5 2
5 6 2
2 4 2
2 3 2
1 5
1 3
1 4
1 2
2 5
*/
- hdu5296
- HDU5296
- hdu5296(倍增lca)
- hdu5296 Annoying problem
- hdu5296 01字典树
- hdu5296 Annoying problem (LCA+SET)
- hdu5296(2015多校1)--Annoying problem(lca+一个公式)
- HDU5296从一棵树上取出若干不连通的点
- 快快快!27个提升效率的iOS开源库推荐
- CodeForces 13E Holes(分块处理)
- 计算程序运行时间(time_t, clock_t)
- UVA 113 Power of Cryptography
- 【随行笔记】与网络编程有关
- HDU5296
- AM335x(TQ335x)学习笔记——WM8960声卡驱动移植
- Linux_多核系统下绑定进程或线程到指定CPU_核执行
- [C++]类的定义 class
- 查看文件被哪个进程lock住
- 百度地图错误解析
- 人脸识别之特征脸方法(Eigenface)PCA方法
- PAT (Advanced Level) 1055. The World's Richest (25) 年龄区间内最有钱的人,结构体排序
- zookeeper使用场景