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

    BZOJ3252: 攻略

    Description

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

    Input

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

    Output

    输出一个整数表示答案

    Sample Input

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

    Sample Output

    10

    题解Here!
    树的形态没有改变,套上树剖。
    问最大价值和,贪心地在吗每个叶子结点中选取树上前缀和最大的节点,计入答案,并删去这个叶子结点到根的所有贡献。
    但是每次到根复杂度经不起了,所以开个$bool$数组记录当前节点是否被删除了贡献,若已删除,则跳出。
    至于区间最值与最值位置,懒得写$ST$表了,直接线段树搞搞事。。。
    线段树真$NB$。。。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define LSON rt<<1
    #define RSON rt<<1|1
    #define DATA(x) b[x].data
    #define POS(x) b[x].pos
    #define SIGN(x) b[x].c
    #define LSIDE(x) b[x].l
    #define RSIDE(x) b[x].r
    #define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
    #define MAXN 200010
    using namespace std;
    int n,m,c=1,d=1;
    int val[MAXN],head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],pos[MAXN],top[MAXN];
    long long sum[MAXN];
    bool used[MAXN];
    struct Tree{
    	int next,to;
    }a[MAXN<<1];
    struct Segment_Tree{
    	long long data,pos,c;
    	int l,r;
    }b[MAXN<<2];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline void add(int x,int y){
    	a[c].to=y;a[c].next=head[x];head[x]=c++;
    	a[c].to=x;a[c].next=head[y];head[y]=c++;
    }
    void dfs1(int rt){
    	son[rt]=0;size[rt]=1;
    	for(int i=head[rt];i;i=a[i].next){
    		int will=a[i].to;
    		if(!deep[will]){
    			deep[will]=deep[rt]+1;
    			sum[will]=sum[rt]+val[will];
    			fa[will]=rt;
    			dfs1(will);
    			size[rt]+=size[will];
    			if(size[son[rt]]<size[will])son[rt]=will;
    		}
    	}
    }
    void dfs2(int rt,int f){
    	id[rt]=d++;pos[id[rt]]=rt;top[rt]=f;
    	if(son[rt])dfs2(son[rt],f);
    	for(int i=head[rt];i;i=a[i].next){
    		int will=a[i].to;
    		if(will!=fa[rt]&&will!=son[rt])dfs2(will,will);
    	}
    }
    inline void pushup(int rt){
    	DATA(rt)=max(DATA(LSON),DATA(RSON));
    	if(DATA(LSON)>DATA(RSON))POS(rt)=POS(LSON);
    	else POS(rt)=POS(RSON);
    }
    inline void pushdown(int rt){
    	if(!SIGN(rt)||LSIDE(rt)==RSIDE(rt))return;
    	SIGN(LSON)+=SIGN(rt);DATA(LSON)+=SIGN(rt);
    	SIGN(RSON)+=SIGN(rt);DATA(RSON)+=SIGN(rt);
    	SIGN(rt)=0;
    }
    void buildtree(int l,int r,int rt){
    	LSIDE(rt)=l;RSIDE(rt)=r;SIGN(rt)=0;
    	if(l==r){
    		DATA(rt)=sum[pos[l]];
    		POS(rt)=l;
    		return;
    	}
    	int mid=l+r>>1;
    	buildtree(l,mid,LSON);
    	buildtree(mid+1,r,RSON);
    	pushup(rt);
    }
    void update(int l,int r,long long c,int rt){
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
    		SIGN(rt)+=c;DATA(rt)+=c;
    		return;
    	}
    	pushdown(rt);
    	int mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)update(l,r,c,LSON);
    	if(mid<r)update(l,r,c,RSON);
    	pushup(rt);
    }
    long long query(int l,int r,int rt){
    	long long ans=0;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return DATA(rt);
    	pushdown(rt);
    	int mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)ans=max(ans,query(l,r,LSON));
    	if(mid<r)ans=max(ans,query(l,r,RSON));
    	return ans;
    }
    void work(){
    	long long ans=0;
    	for(int i=1;i<=m;i++){
    		ans+=query(1,n,1);
    		int x=pos[POS(1)];
    		while(x&&used[x]){
    			update(id[x],id[x]+size[x]-1,-val[x],1);
    			used[x]=false;
    			x=fa[x];
    		}
    	}
    	printf("%lld
    ",ans);
    }
    void init(){
    	int x,y;
    	n=read();m=read();
    	for(int i=1;i<=n;i++){
    		val[i]=read();
    		used[i]=true;
    	}
    	for(int i=1;i<n;i++){
    		x=read();y=read();
    		add(x,y);
    	}
    	deep[1]=1;sum[1]=val[1];
    	dfs1(1);
    	dfs2(1,1);
    	buildtree(1,n,1);
    }
    int main(){
    	init();
    	work();
        return 0;
    }
    
  • 相关阅读:
    uva 1606 amphiphilic carbon molecules【把缩写写出来,有惊喜】(滑动窗口)——yhx
    Uva10082 WERTYU -S.B.S.
    Quicksum-S.B.S.
    NOIP2014提高组 DAY1 -SilverN
    NOIP2013普及组 -SilverN
    uva 1354 Mobile Computing ——yhx
    UVa 11292 Dragon of Loowater
    UVa 839 Not so Mobile
    Quicksum -SilverN
    uva 140 bandwidth (好题) ——yhx
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9503305.html
Copyright © 2011-2022 走看看