HDU 5296 Annoying problem (LCA,变形)
题意:
给一棵n个节点的树,再给q个操作,初始集合S为空,每个操作要在一个集合S中删除或增加某些点,输出每次操作后:要使得集合中任意两点互可达所耗最小需要多少权值。(记住只能利用原来给的树边。给的树边已经有向。10万个点,10万个操作)
思路:只能用 O(nlogn)的复杂度。官方题解:

重点也就是要找到集合S中的以x和y为端点一条链,使得操作点u到达这条链是最近的。删除也是这样,找到这条链,删除u到这链的路长。
步骤:
(1)记录从根遍历的DFS序。
(2)计算每个点到根的路径所经过边的权之和。
(3)对于每个操作,无论哪种,如果u的序最大,那么在比u的序小的里面挑一个最大x和一个最小y。再按照式子就可算出,如果是插入就加上这个权和,否则就是减去。
#include <bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=;
vector<int> chld[N]; //孩子
unordered_map<int,int> weight[N];
int dis[N];
int mapp[N];
int seq[N]; //seq记录DFS序
int anti_seq[N]; //anti记录第几个访问的是谁
bool inset[N];
int ans, num;
set<int> sett; void DFS(int x)
{
seq[x]=++num;
for(int i=; i<chld[x].size(); i++)
{
int t=chld[x][i];
if(!seq[t]) DFS(t);
}
} unordered_map<int,int> vis;
int LCA(int a,int b)
{
vis.clear();
while(mapp[a])
{
vis[a]=;
a=mapp[a];
}
vis[a]=;
while( !vis[b] ) b=mapp[b];
return b;
} void cal_weight(int n)
{
for(int i=; i<=n; i++)
{
int sum=, s=i;
while(mapp[s])
{
sum+=weight[mapp[s]][s];
s=mapp[s];
}
dis[i]=sum;
}
} int ins(int u)
{
sett.insert(seq[u]);
if(sett.size()==) {ans=;return ;} set<int>::iterator it=sett.find(seq[u]); int x=, y=;
if(*it==*sett.begin()) //已经是最小
{
x=anti_seq[*(++it)];
y=anti_seq[*(sett.rbegin())];
}
else if(*it==*sett.rbegin()) //已经是最大
{
x=anti_seq[*(--it)];
y=anti_seq[*(sett.begin())];
}
else
{
x=anti_seq[ *(--it)];
y=anti_seq[ *(++(++it)) ];
} ans+=dis[u]-dis[LCA(u,x )]- dis[LCA(u,y )] + dis[LCA(x,y)];
return ans;
} int del(int u)
{
if(sett.size()==)
{
sett.erase(seq[u]);
ans=;
return ;
} set<int>::iterator it=sett.find(seq[u]);
int x=, y=;
if(*it==*sett.begin()) //已经是最小
{
x=anti_seq[*(++it)];
y=anti_seq[*(sett.rbegin())];
}
else if(*it==*sett.rbegin()) //已经是最大
{
x=anti_seq[*(--it)];
y=anti_seq[*(sett.begin())];
}
else
{
x=anti_seq[ *(--it)];
y=anti_seq[ *(++(++it)) ];
}
ans-=dis[u]-dis[LCA(u,x )]- dis[LCA(u,y )] + dis[LCA(x,y)];
sett.erase(seq[u]);
return ans;
} int main()
{
freopen("input.txt", "r", stdin);
int a, b, c, t, q, n, j=;
cin>>t;
while(t--)
{
scanf("%d%d", &n, &q);
for(int i=; i<=n+; i++) chld[i].clear(),weight[i].clear(); memset(inset, , sizeof(inset));
memset(seq, , sizeof(seq));
memset(anti_seq, , sizeof(anti_seq));
memset(mapp, , sizeof(mapp));
memset(dis,,sizeof(dis));
sett.clear();
ans=;
num=; for(int i=; i<n; i++)
{
scanf("%d%d%d",&a,&b,&c);
chld[a].push_back(b);
weight[a][b]=c;
mapp[b]=a;
}
printf("Case #%d:\n",++j);
int root=n; //获得树根
while(mapp[root]) root=mapp[root];
DFS(root); //获得DFS序 for(int i=; i<=n; i++) anti_seq[seq[i]]=i; //反向索引
cal_weight(n); //计算每个点到根的权
while(q--)
{
scanf("%d%d",&a,&b);
if(a==) //如果不存在于集合中,则插,有则不插
{
if(inset[b]) printf("%d\n", ans); //已经存在,不必计算
else
{
inset[b]=;
printf("%d\n", ins(b));
}
}
else //如果存在于集合中,则删,否则不删。
{
if(inset[b]) //存在,要删
{
inset[b]=;
printf("%d\n",del(b));
}
else printf("%d\n",ans);
}
}
}
return ;
}
AC代码
HDU 5296 Annoying problem (LCA,变形)的更多相关文章
- HDU 5296 Annoying problem LCA+树状数组
题解链接 Annoying problem Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/O ...
- HDU 5296 Annoying problem dfs序 lca
Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5296 Description Coco has a tree, w ...
- HDU 5296 Annoying problem dfs序 lca set
Annoying problem Problem Description Coco has a tree, whose nodes are conveniently labeled by 1,2,…, ...
- HDU 5296 Annoying problem
Annoying problem Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
- 2015 Multi-University Training Contest 1 hdu 5296 Annoying problem
Annoying problem Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
- HDOJ 5296 Annoying problem LCA+数据结构
dfs一遍得到每一个节点的dfs序,对于要插入的节点x分两种情况考虑: 1,假设x能够在集合中的某些点之间,找到左边和右边距离x近期的两个点,即DFS序小于x的DFS序最大点,和大于x的DFS序最小的 ...
- HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca
Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...
- hdu5296(2015多校1)--Annoying problem(lca+一个公式)
Annoying problem Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
- 【HDOJ】5296 Annoying problem
LCA+RMQ.挺不错的一道题目. 思路是如何通过LCA维护费用.当加入新的点u是,费用增量为dis[u]-dis[lca(u, lower_u)] - dis[lca(u, greater_u)] ...
随机推荐
- uoj 67 新年的毒瘤 割点
题目链接: 题目 #67. 新年的毒瘤 问题描述 辞旧迎新之际,喜羊羊正在打理羊村的绿化带,然后他发现了一棵长着毒瘤的树. 这个长着毒瘤的树可以用 nn 个结点 mm 条无向边的无向图表示.这个图中有 ...
- 【BZOJ】【1934】【SHOI 2007】Vote 善意的投票
网络流/最小割 简单题= =直接利用最小割的性质: 割掉这些边后,将所有点分成了两部分(两个连通块),我们可以假定与S相连的是投赞成票,与T相连的是投反对票. 那么如果一个小朋友原本意愿是睡觉,那么连 ...
- Eclipse plugin插件开发 NoClassDefFoundError
Eclipse的每一个plugin都有属于自己的类加载器,这是OSGI架构的基础,每一个plugin项目都是一个bundle,独立运行在各自的运行环境里面,这就造成了开发时和运行时的不同. Eclip ...
- uva 307
排序之后再剪枝,有点神 #include <cstdio> #include <cstdlib> #include <cmath> #include <map ...
- windowopen
1.最基本的弹出窗口代码] <SCRIPT LANGUAGE="javascript"> <!-- window.open ('page.html') --> ...
- POJ1416Shredding Company
http://poj.org/problem?id=1416 题意 : 要为碎纸机公司开发一种新的碎纸机,这种碎纸机要具有3个特性 :一是粉碎机以一个目标数 t 作为输入,并且粉碎的纸上写有一个数字n ...
- *[topcoder]TaroFriends
http://community.topcoder.com/stat?c=problem_statement&pm=13005 好题.最暴力是试验2^n种跳法.然后有从结果入手,那么最终的左右 ...
- Tomcat处理HTTP请求源码分析(上)(转)
转载自:http://www.infoq.com/cn/articles/zh-tomcat-http-request-1 很多开源应用服务器都是集成tomcat作为web container的,而且 ...
- Tomcat部署问题,Tomcat集群部署问题。
1.服务器崩溃,指的是Tomcat程序崩溃,还是服务器系统崩溃? 答:都有可能. 所以一台服务器上部署多个Tomcat可以防止程序崩溃问题.但不能避免服务器崩溃,要避免服务器崩溃,就要采用服务器集群. ...
- Java Logger(java日志)
目录 1. 简介2. 安装3. log4j基本概念3.1. Logger3.2. Appender3.2.1. 使用ConsoleAppender3.2.2. 使用FileAppender3.2.3. ...