zoukankan      html  css  js  c++  java
  • [SDOI2015]寻宝游戏

    [SDOI2015]寻宝游戏

    题目大意:

    一个(n(nle10^5))个点的带边权的树,初始每个结点都是白色。(m(mle10^5))次操作,每次将一个点涂黑/白,问包含所有黑点的最小权连通块。

    思路:

    set以DFS序为序维护所有黑点,答案即为set内相邻结点距离和+头尾结点距离。

    源代码:

    #include<set>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<climits>
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    typedef long long int64;
    const int N=1e5+1,logN=17;
    struct Edge {
    	int to,w;
    };
    std::vector<Edge> e[N];
    inline void add_edge(const int &u,const int &v,const int &w) {
    	e[u].push_back((Edge){v,w});
    	e[v].push_back((Edge){u,w});
    }
    bool w[N];
    int dep[N],anc[N][logN],dfn[N],id[N];
    int64 dis[N],tmp;
    std::set<int> set;
    inline int lg2(const float &x) {
    	return ((unsigned&)x>>23&255)-127;
    }
    void dfs(const int &x,const int &par) {
    	anc[x][0]=par;
    	dep[x]=dep[par]+1;
    	id[dfn[x]=++dfn[0]]=x;
    	for(register int i=1;i<=lg2(dep[x]);i++) {
    		anc[x][i]=anc[anc[x][i-1]][i-1];
    	}
    	for(unsigned i=0;i<e[x].size();i++) {
    		const int &y=e[x][i].to,&w=e[x][i].w;
    		if(y==par) continue;
    		dis[y]=dis[x]+w;
    		dfs(y,x);
    	}
    }
    inline int lca(int x,int y) {
    	if(dep[x]<dep[y]) std::swap(x,y);
    	for(register int i=lg2(dep[x]-dep[y]);i>=0;i--) {
    		if(dep[anc[x][i]]>=dep[y]) x=anc[x][i];
    	}
    	for(register int i=lg2(dep[x]);i>=0;i--) {
    		if(anc[x][i]!=anc[y][i]) {
    			x=anc[x][i];
    			y=anc[y][i];
    		}
    	}
    	return x==y?x:anc[x][0];
    }
    inline int64 dist(const int &x,const int &y) {
    	const int z=lca(x,y);
    	return dis[x]+dis[y]-dis[z]*2;
    }
    inline int64 dist2() {
    	const int x=*++set.begin();
    	const int y=*++set.rbegin();
    	if(x==INT_MIN||y==INT_MAX) return 0;
    	return dist(id[x],id[y]);
    }
    inline void ins(const int &x) {
    	const std::set<int>::iterator p=--set.lower_bound(x);
    	const std::set<int>::iterator q=set.upper_bound(x);
    	if(*p!=INT_MIN) tmp+=dist(id[x],id[*p]);
    	if(*q!=INT_MAX) tmp+=dist(id[x],id[*q]);
    	if(*p!=INT_MIN&&*q!=INT_MAX) tmp-=dist(id[*p],id[*q]);
    	set.insert(x);
    }
    inline void del(const int &x) {
    	const std::set<int>::iterator p=--set.lower_bound(x);
    	const std::set<int>::iterator q=set.upper_bound(x);
    	if(*p!=INT_MIN) tmp-=dist(id[x],id[*p]);
    	if(*q!=INT_MAX) tmp-=dist(id[x],id[*q]);
    	if(*p!=INT_MIN&&*q!=INT_MAX) tmp+=dist(id[*p],id[*q]);
    	set.erase(x);
    }
    int main() {
    	const int n=getint(),m=getint();
    	for(register int i=1;i<n;i++) {
    		const int u=getint(),v=getint();
    		add_edge(u,v,getint());
    	}
    	dfs(1,0);
    	set.insert(INT_MIN);
    	set.insert(INT_MAX);
    	for(register int i=0;i<m;i++) {
    		const int x=dfn[getint()];
    		if(w[x]) del(x);
    		w[x]^=1;
    		if(w[x]) ins(x);
    		printf("%lld
    ",tmp+dist2());
    	}
    	return 0;
    }
    
  • 相关阅读:
    [LeetCode] 60. Permutation Sequence 序列排序
    [LeetCode] 31. Next Permutation 下一个排列
    [LeetCode] 47. Permutations II 全排列 II
    [LeetCode] 46. Permutations 全排列
    [LeetCode] 77. Combinations 全组合
    利用 Json.Net 将对象转换成Json
    使用sqlmetal工具自动生成SQL数据库的Linq类文件
    SharePoint 2013 设置 显示详细错误信息 修改位置总结
    本地访问Vmware虚机Web网站
    Web项目HttpContext.Current 为空
  • 原文地址:https://www.cnblogs.com/skylee03/p/10042610.html
Copyright © 2011-2022 走看看