博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一本通1554【例 3】异象石
阅读量:5012 次
发布时间:2019-06-12

本文共 3681 字,大约阅读时间需要 12 分钟。

时间限制: 1000 ms         内存限制: 524288 KB

题目描述

原题来自:

在 Adera 的异时空中有一张地图。这张地图上有 N 个点,有 N1 条双向边把它们连通起来。起初地图上没有任何异象石,在接下来的 M 个时刻中,每个时刻会发生以下三种类型的事件之一:

  1. 地图的某个点上出现了异象石(已经出现的不会再次出现);
  2. 地图某个点上的异象石被摧毁(不会摧毁没有异象石的点);
  3. 向玩家询问使所有异象石所在的点连通的边集的总长度最小是多少。

请你作为玩家回答这些问题。下图是一个例子,灰色节点表示出现了异象石,加粗的边表示被选为连通异象石的边集。

stone.png

输入格式

第一行有一个整数 N,表示点的个数;

接下来 N1 行每行三个整数 x,y,z,表示点 x 和 y 之间有一条长度为 z 的双向边;

第 N+1 行有一个正整数 M;

接下来 M 行每行是一个事件,事件是以下三种格式之一:

  • + x:表示点 x 上出现了异象石;
  • - x:表示点 x 上的异象石被摧毁;
  • ?:表示询问使当前所有异象石所在的点连通所需的边集的总长度最小是多少。

输出格式

对于每个 ? 事件,输出一个整数表示答案。

样例

样例输入

6 1 2 1 1 3 5 4 1 7 4 5 3 6 4 2 10 + 3 + 1 ? + 6 ? + 5 ? - 6 - 3 ?

样例输出

5 14 17 10

数据范围与提示

对于 30% 的数据,1n,m10^3;

对于另 20% 的数据,地图是一条链,或者一朵菊花;

对于 100% 的数据,1n,m10^5,1x,yn,x !=y,1z10^9。

 

sol:先考虑下给你一堆点怎么求把他们全部连起来需要的费用,发现就是从一个点以任意顺序依次遍历每个点再回到出发点的边权和的1/2,之后就会容易一点,假定这是以dfs遍历的,弄一个set,加点删点是对应的加上几条路径或减去几条就可以了

#include 
using namespace std;const int N=100005,M=200005,inf=0x3f3f3f3f;int n,m;struct Tree{ int tot,Next[M],to[M],val[M],head[N]; inline void add(int x,int y,int z) { Next[++tot]=head[x]; to[tot]=y; val[tot]=z; head[x]=tot; return; } int Id_cnt,Id[N],Xuhao[N]; //dfs序 bool Inset[N]; int Depth[N],F[N][23]; long long Dis[N]; inline void dfs(int x,int fa) { Id[++Id_cnt]=x; Xuhao[x]=Id_cnt; F[x][0]=fa; Depth[x]=Depth[fa]+1; int i; for(i=head[x];i;i=Next[i]) if(to[i]!=fa) { Dis[to[i]]=Dis[x]+val[i]; dfs(to[i],x); } return; } set
Set; inline void Pre() { int i,j; dfs(1,0); for(i=1;i<=19;i++) { for(j=1;j<=n;j++) F[j][i]=F[F[j][i-1]][i-1]; } Set.insert(-inf); Set.insert(inf); return; } inline int Ask_Lca(int x,int y) { int i; if(Depth[x]
=Depth[y]) { x=F[x][i]; } if(x==y) return x; for(i=19;~i;i--) if(F[x][i]!=F[y][i]) { x=F[x][i]; y=F[y][i]; } return F[x][0]; } inline long long Ask_Dis(int x,int y) { return Dis[x]+Dis[y]-(Dis[Ask_Lca(x,y)]<<1); } long long Dis_All; inline void Point_Add(int x) { if(Inset[Xuhao[x]]) return; Set.insert(Xuhao[x]); Inset[Xuhao[x]]=1; set
::iterator it=Set.upper_bound(Xuhao[x]); int p2=(*it),p1=(*(--(--it)));// printf("%d %d\n",p1,p2);// puts("EEE"); if(p1!=-inf) Dis_All+=Ask_Dis(Id[p1],x); if(p2!=inf) Dis_All+=Ask_Dis(x,Id[p2]);// puts("FFF"); if((p1!=-inf)&&(p2!=inf)) Dis_All-=Ask_Dis(Id[p1],Id[p2]); return; } inline void Point_Del(int x) { if(!Inset[Xuhao[x]]) return; Set.erase(Xuhao[x]); Inset[Xuhao[x]]=0; set
::iterator it=Set.upper_bound(Xuhao[x]); int p2=(*it),p1=(*(--it)); if(p1!=-inf) Dis_All-=Ask_Dis(Id[p1],x); if(p2!=inf) Dis_All-=Ask_Dis(x,Id[p2]); if((p1!=-inf)&&(p2!=inf)) Dis_All+=Ask_Dis(Id[p1],Id[p2]); return; } inline long long Get_ans() { long long DD=(Set.size()>3)?(Ask_Dis(Id[*(Set.upper_bound(-inf))],Id[*(--Set.lower_bound(inf))])):0; return (Dis_All+DD)>>1; } inline void Init() { tot=Dis_All=Id_cnt=0; memset(head,0,sizeof head); memset(Inset,0,sizeof Inset); return; }}T;int main(){// freopen("stone6.in","r",stdin);// freopen("my.out","w",stdout); int i; scanf("%d",&n); for(i=1;i
View Code

 

转载于:https://www.cnblogs.com/gaojunonly1/p/10352761.html

你可能感兴趣的文章
Elastic Search 语法总结
查看>>
py自动化之环境配置
查看>>
Winodws SNMP服务安装和配置(Windows 2003 & 2008 R2)
查看>>
红黑树-想说爱你不容易
查看>>
【题目】英文字符进行频率的统计,直方图输出
查看>>
LeetCode-Binary Tree Level Order Traversal
查看>>
COM组件开发实践
查看>>
yii2 源码分析1从入口开始
查看>>
浅谈网站推广
查看>>
Away3D基础之摄像机
查看>>
Leetcode 128. Longest Consecutive Sequence
查看>>
程序员必须知道的几个Git代码托管平台
查看>>
导电塑料入梦来
查看>>
C# 线程手册 第五章 扩展多线程应用程序 - 什么是线程池
查看>>
笔记1126ASP.NET面试题(转)
查看>>
考研路茫茫--单词情结 - HDU 2243(AC自动机+矩阵乘法)
查看>>
HTTP运行期与页面执行模型
查看>>
tableView优化方案
查看>>
近期思考(2019.07.20)
查看>>
Apache2.4使用require指令进行访问控制
查看>>