zoukankan      html  css  js  c++  java
  • 【BZOJ3991】【SDOI2011】—寻宝游戏(虚树+Set)

    传送门

    其实这道题并没有用到真正的虚树

    不过用到了虚树的思想

    因为考虑到其实对于一个点总是要走到和走出

    可以发现最短的走法就是dfsdfs序的走法

    那么我们只需要按照dfsdfs序维护一下所有宝藏所在节点就可以了

    用个setset就解决了

    每次新的点就查一下前驱结点和后继结点

    加减一下disdis

    特判一下只有一个点或者没有点的情况

    还有注意会爆intint

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=1000005;
    int a[N],adj[N],ans,dfn[N],nxt[N<<1],anc[N],to[N<<1],val[N<<1],dis[N],cnt;
    int tot,dep[N],top[N],siz[N],fa[N],son[N];
    int n,m;
    struct node{
    	int id;
    	inline bool operator <(const node a)const{
    		return dfn[id]<dfn[a.id];
    	}
    }p[N];
    inline void addedge(int u,int v,int w){
    	nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,val[cnt]=w;
    }
    inline void dfs1(int u){
    	siz[u]=1;dfn[u]=++tot,p[u].id=u;
    	for(int e=adj[u];e;e=nxt[e]){
    		int v=to[e];
    		if(v==fa[u])continue;
    		fa[v]=u,dep[v]=dep[u]+1,dis[v]=dis[u]+val[e];
    		dfs1(v),siz[u]+=siz[u];
    		if(siz[u]>siz[son[u]])son[u]=v;
    	}
    }
    inline void dfs2(int u,int tp){
    	top[u]=tp;
    	if(!son[u])return;
    	dfs2(son[u],tp);
    	for(int e=adj[u];e;e=nxt[e]){
    		int v=to[e];
    		if(v==fa[u]||v==son[u])continue;
    		dfs2(v,v);
    	}
    }
    inline int Lca(int u,int v){
    	while(top[u]!=top[v]){
    		if(dep[top[u]]<dep[top[v]])swap(u,v);
    		u=fa[top[u]];
    	}
    	if(dep[u]<dep[v])swap(u,v);
    	return v;
    }
    set<node> st;
    set<node>::iterator pl,pr;
    inline set<node>::iterator pre(set<node>::iterator a){
    	if(a==st.begin())a=st.end();a--;return a;
    }
    inline int dist(int u,int v){
    	int lca=Lca(u,v);
    	return (dis[u]+dis[v]-2*dis[lca]);
    }
    inline set<node>::iterator next(set<node>::iterator a){
    	a++;
    	if(a==st.end())a=st.begin();
    	return a;
    }
    signed main(){
    	n=read(),m=read();
    	for(int i=1;i<n;i++){
    		int u=read(),v=read(),w=read();
    		addedge(u,v,w),addedge(v,u,w);
    	}
    	dfs1(1);
    	dfs2(1,1);
    	for(int i=1;i<=m;i++){
    		int u=read();
    		if(st.find((node){u})!=st.end()){
    			if(st.size()!=1){
    				pl=pr=st.find((node){u});
    				pl=pre(pl),pr=next(pr);
    				ans-=dist(u,(*pl).id)+dist(u,(*pr).id);
    				ans+=dist((*pl).id,(*pr).id);
    			}
    			st.erase((node){u});
    		}
    		else{
    			st.insert((node){u});
    			if(st.size()!=1){
    				pl=pr=st.find((node){u});
    				pl=pre(pl),pr=next(pr);
    				ans+=dist(u,(*pl).id)+dist(u,(*pr).id);
    				ans-=dist((*pl).id,(*pr).id);
    			}
    		}
    		anc[i]=ans;
    	}
    	for(int i=1;i<=m;i++)cout<<anc[i]<<'
    ';
    }
    
  • 相关阅读:
    五大常用算法之二:动态规划算法
    五大常用算法之一:分治算法
    c++控制台程序实现定时器
    Oracle sqlplus设置显示格式命令详解
    存储的基本概念谈
    类UNIX操作系统概念
    从源代码到可执行文件
    SQL更改表字段为自增标识
    enum和int、string的转换操作
    SEO技巧汇集
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366335.html
Copyright © 2011-2022 走看看