zoukankan      html  css  js  c++  java
  • BZOJ3252: 攻略

    Description

    题目简述:树版[k取方格数]
     
    众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏。
    今天他得到了一款新游戏《XX半岛》,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景。所有场景和选择支构成树状结构:开始游戏时在根节点(共通线),叶子节点为结局。每个场景有一个价值,现在桂马开启攻略之神模式,同时攻略k次该游戏,问他观赏到的场景的价值和最大是多少(同一场景观看多次是不能重复得到价值的)
    “为什么你还没玩就知道每个场景的价值呢?”
    “我已经看到结局了。”

    Input

    第一行两个正整数n,k
    第二行n个正整数,表示每个场景的价值
    以下n-1行,每行2个整数a,b,表示a场景有个选择支通向b场景(即a是b的父亲)
    保证场景1为根节点

    Output

     
    输出一个整数表示答案

    Sample Input

    5 2
    4 3 2 1 1
    1 2
    1 5
    2 3
    2 4

    Sample Output

    10

    HINT

    对于100%的数据,n<=200000,1<=场景价值<=2^31-1

     
    很容易得到这样一个贪心策略:每次优先找一条从根开始的权值最大的路径,然后用数据结构修改其他路径的权值。
    因为一个场景最多被选1次,所以每次顺着路径的末节点向上一直修改到上一个被选择的节点,这样修改的时间复杂度就是O(N)*O(数据结构)。
    因为场景会影响一个子树内所有的节点,所以这里的数据结构用棵线段树就行了,时间复杂度为O(NlogN)。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
    	if(head==tail) {
    		int l=fread(buffer,1,BufferSize,stdin);
    		tail=(head=buffer)+l;
    	}
    	return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const int maxn=200010;
    int n,k,A[maxn],first[maxn],next[maxn],to[maxn],e;
    void AddEdge(int v,int u) {to[++e]=v;next[e]=first[u];first[u]=e;}
    int st[maxn],en[maxn],pos[maxn],fa[maxn],del[maxn],cnt;
    ll val[maxn];
    void dfs(int x) {
    	st[x]=++cnt;pos[cnt]=x;val[x]+=A[x];
    	ren val[to[i]]=val[x],fa[to[i]]=x,dfs(to[i]);
    	en[x]=cnt;
    }
    struct Ans {int p;ll v;}maxv[maxn<<2];
    Ans better(Ans A,Ans B) {
    	if(A.v>B.v) return A;
    	return B;
    }
    ll addv[maxn<<2];
    void maintain(int o,int l,int r) {
    	int lc=o<<1,rc=lc|1;
    	if(l<r) maxv[o]=better(maxv[lc],maxv[rc]);
    	else maxv[o]=(Ans){l,0};
    	if(addv[o]) maxv[o].v+=addv[o];
    }
    void build(int o,int l,int r) {
    	if(l==r) addv[o]=val[pos[l]];
    	else {
    		int mid=l+r>>1,lc=o<<1,rc=lc|1;
    		build(lc,l,mid);build(rc,mid+1,r);
    	}
    	maintain(o,l,r);
    }
    void update(int o,int l,int r,int ql,int qr,int v) {
    	if(ql<=l&&r<=qr) addv[o]+=v;
    	else {
    		int mid=l+r>>1,lc=o<<1,rc=lc|1;
    		if(addv[o]) addv[lc]+=addv[o],addv[rc]+=addv[o],addv[o]=0;
    		if(ql<=mid) update(lc,l,mid,ql,qr,v);
    		else maintain(lc,l,mid);
    		if(qr>mid) update(rc,mid+1,r,ql,qr,v);
    		else maintain(rc,mid+1,r);
    	}
    	maintain(o,l,r);
    }
    int main() {
    	n=read();k=read();
    	rep(i,1,n) A[i]=read();
    	rep(i,1,n-1) AddEdge(read(),read());
    	dfs(1);build(1,1,n);ll ans=0;
    	while(k--) {
    		Ans x=maxv[1];ans+=x.v;
    		if(!x.v) break;
    		int u=pos[x.p];
    		while(u&&!del[u]) {
    			del[u]=1;
    			update(1,1,n,st[u],en[u],-A[u]);
    			u=fa[u];
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    JAVA-初步认识-第七章-默认构造函数
    JAVA-初步认识-第七章-面向对象-构造函数-概述
    JAVA-初步认识-第六章-应用场景
    JAVA-初步认识-第六章-二维数组-另一种定义方式
    JAVA-初步认识-第六章-二维数组-定义方式内存图解2
    JAVA-初步认识-第六章-二维数组-定义方式内存图解
    通过IFeatureClass 接口查询 IWorkspace, 查询通配符
    failed to register esriAddin
    DataGridView实时提交
    ArcGIS AddIn开发笔记(一)
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5578305.html
Copyright © 2011-2022 走看看