zoukankan      html  css  js  c++  java
  • [SDOI2011]消耗战 题解

    题面

    虚树的模板题:

    虚树的思想是只保留有用的点(在这道题目里面显然是标记点和lca),然后重新构建一棵树,从而使节点大大减少,优化复杂度

    我们维护一条链(以1号点为根),这条链左边的所有在虚树上的位置都已经处理完毕;而这条链右边的和下面的都未处理;

    这条链我们用栈来维护;

    对于要新加的询问点now,对于虚树的影响有四种情况:(lc表示x与st[top]的LCA)

    1.lc==st[top]      :  在虚树上连接st[top]与now                                   

    .

    2.lc在st[top]与st[top-1]之间;在虚树上连接lc与st[top],--top,然后now进栈;

    3.lc==st[top-1]    :--top,然后now进栈;

    4.lc在st[top-1]之上 :在虚树上连接st[top-1]与st[top],然后退栈,重复以上步骤知道出现情况1、2、3;

    在最后,我们把这条链加入到虚树中,这样一颗完美的虚树就建成了;

    在每次建立虚树的时候,我们要实时清空虚树,否则时间复杂度会退化成O(n^2);

    然后在这个虚树上跑dp,就可以了;

    #include <bits/stdc++.h>
    #define int long long
    #define inc(i,a,b) for(register int i=a;i<=b;i++)
    #define dec(i,a,b) for(register int i=a;i>=b;i--)
    using namespace std;
    int head1[500010],cnt1,head2[500010],cnt2;
    class littlestar{
    	public:
    	int to,nxt;
    	long long w;
    	void add1(int u,int v,long long gg){
    		to=v; nxt=head1[u];
    		head1[u]=cnt1; w=gg;
    	}
    	void add2(int u,int v){
    		to=v; nxt=head2[u];
    		head2[u]=cnt2;
    	}
    }star1[500010*2],star2[500010*2];
    int n,f[500010][25],dfn[500010],cur,dep[500010];
    long long minv[500010];
    void dfs(int u)
    {
    	inc(i,0,19){
    		f[u][i+1]=f[f[u][i]][i];
    	}
    	dfn[u]=++cur;
    	for(int i=head1[u];i;i=star1[i].nxt){
    		int v=star1[i].to;
    		if(!dfn[v]){
    			f[v][0]=u;
    			dep[v]=dep[u]+1;
    			minv[v]=min(minv[u],star1[i].w);
    			dfs(v);
    		}
    	}
    }
    int lca(int x,int y)
    {
    	if(dep[x]<dep[y]) swap(x,y);
    	dec(i,20,0){
    		if(dep[f[x][i]]>=dep[y]) x=f[x][i];
    	}
    	if(x==y) return x;
    	dec(i,20,0){
    		if(f[x][i]!=f[y][i]){
    			x=f[x][i]; y=f[y][i];
    		}
    	}
    	return f[x][0];
    }
    bool cmp(int x,int y){return dfn[x]<dfn[y];}
    int num;
    int judge[500001],h[500010];
    int st[500010],top;
    int dp(int u)
    {
    	long long summ=0;
    	for(int i=head2[u];i;i=star2[i].nxt){
    		int v=star2[i].to;
    		summ+=dp(v);
    	}
    	long long ans=0;
    	if(judge[u]) ans=minv[u];
    	else ans=min(minv[u],summ);
    	judge[u]=0;
    	head2[u]=0;
    	return ans;
    }
    signed main()
    {
    	cin>>n;
    	inc(i,1,n-1){
    		int u,v; long long w;
    		scanf("%lld%lld%lld",&u,&v,&w);
    		star1[++cnt1].add1(u,v,w);
    		star1[++cnt1].add1(v,u,w);
    	}
    	minv[1]=1e17+21;
    	dfs(1);
    	int q; scanf("%lld",&q);
    	while(q--){
    		scanf("%lld",&num);
    		inc(i,1,num){
    			scanf("%lld",&h[i]);
    			judge[h[i]]=1;
    		}
    		sort(h+1,h+1+num,cmp);
    		top=1;
    		st[top]=h[1];
    		inc(i,2,num){
    			int LCA=lca(h[i],st[top]);
    			while(true){
    				if(dep[LCA]>=dep[st[top-1]]){
    					if(LCA!=st[top]){
    						star2[++cnt2].add2(LCA,st[top]);
    						if(LCA!=st[top-1]){
    							st[top]=LCA;
    						}
    						else{
    							--top;
    						}
    					}
    					else{
    						break;
    					}
    				}
    				else{
    					star2[++cnt2].add2(st[top-1],st[top]);
    					--top;
    				}
    			}
    			st[++top]=h[i];
    		}
    		while(--top){
    			star2[++cnt2].add2(st[top],st[top+1]);
    		}
    		cout<<dp(st[1])<<endl;
    		cnt2=0;
    	}
    }
    
  • 相关阅读:
    17、springcloud整合lettuce使用redis
    16、springcloud整合Swagger2构建Restful服务的APIs
    15、Feign整合断路器监控Hystrix Dashboard
    14、Ribbon整合断路器监控Hystrix Dashboard
    13、如何使用断路器监控Hystrix Dashboard
    12、Feign整合断路器Hystrix
    wince中对ini文件的操作
    winform应用程序更新 带进度条
    wince隐藏任务栏
    一文学会JVM性能优化
  • 原文地址:https://www.cnblogs.com/kamimxr/p/12031362.html
Copyright © 2011-2022 走看看