博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj3252攻略(线段树+dfs序)
阅读量:5107 次
发布时间:2019-06-13

本文共 2885 字,大约阅读时间需要 9 分钟。

3252: 攻略

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 562  Solved: 238
[][][]

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

 

Source

 

/*嗯,需要维护每个点到根的距离。首先开始的时候选取叶子结点一定比中间节点优。 当选择了一条链的时候,会对哪些点有影响呢?答案当然是在这条链上的点的子树。把这个点的子树权值减掉这个点的权值就好。看到子树,想到dfs序。又因为要查询最大值,所以可以想到用线段树实现。线段树每个节点维护原树每个点到根的距离的最大值和原树每个节点dfs序所对应的点的编号。 每次查询区间最大值,然后删去这条链,每次删的时候更新子树权值(区间减法)。删除把这个点的权值赋值为0就好。然后往上走,走的时候到某个点权值为0那么就停。因为如果某个点权值为0,那么他到根的路径上所有点权都为零。恩。 */#include
#include
#include
#define N 200007#define ll long longusing namespace std;ll n,m,ans,cnt,tot;ll head[N],dis[N],fa[N];ll S[N],pos[N],T[N],a[N];struct edge{ int u,v,net,w;}e[N<<1];struct tree{ ll l,r,mx,pos,flag;}tr[N<<2];namespace seg{ void pushup(int k) { if(tr[k<<1].mx>tr[k<<1|1].mx) tr[k].mx=tr[k<<1].mx,tr[k].pos=tr[k<<1].pos; else tr[k].mx=tr[k<<1|1].mx,tr[k].pos=tr[k<<1|1].pos; } void pushdown(int k) { tr[k<<1].flag+=tr[k].flag;tr[k<<1|1].flag+=tr[k].flag; tr[k<<1].mx+=tr[k].flag;tr[k<<1|1].mx+=tr[k].flag; tr[k].flag=0; } void build(int k,int l,int r) { tr[k].l=l;tr[k].r=r; if(l==r) { tr[k].mx=dis[pos[l]],tr[k].pos=pos[l]; return; } int mid=l+r>>1; build(k<<1,l,mid);build(k<<1|1,mid+1,r); pushup(k); } void update(int k,int l,int r,int z) { if(tr[k].l==l && tr[k].r==r) { tr[k].mx+=z;tr[k].flag+=z; return; } pushdown(k); int mid=tr[k].l+tr[k].r>>1; if(r<=mid) update(k<<1,l,r,z); else if(l>mid) update(k<<1|1,l,r,z); else update(k<<1,l,mid,z),update(k<<1|1,mid+1,r,z); pushup(k); }}using namespace seg;inline void add(int u,int v){ e[++cnt].v=v;e[cnt].net=head[u];head[u]=cnt;}inline ll read(){ ll x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){
if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f;}void dfs(int u,int last,ll sum){ S[u]=++tot;pos[tot]=u;dis[u]=sum; for(int i=head[u];i;i=e[i].net) { int v=e[i].v; if(v==last) continue; fa[v]=u;dfs(v,u,sum+a[v]); }T[u]=tot;}void change(int u){ while(a[u]) { update(1,S[u],T[u],-a[u]); a[u]=0;u=fa[u]; }}int main(){ int x,y; n=read();m=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i

 

转载于:https://www.cnblogs.com/L-Memory/p/7756865.html

你可能感兴趣的文章
MyEclipse10安装SVN插件
查看>>
[转]: 视图和表的区别和联系
查看>>
Regular Experssion
查看>>
python中的字符编码
查看>>
图论例题1——NOIP2015信息传递
查看>>
uCOS-II中的任务切换-图解多种任务调度时机与问题
查看>>
CocoaPods的安装和使用那些事(Xcode 7.2,iOS 9.2,Swift)
查看>>
Android 官方新手指导教程
查看>>
幸运转盘v1.0 【附视频】我的Android原创处女作,请支持!
查看>>
UseIIS
查看>>
为什么int型最大的数是2147483647
查看>>
数据库连接的三层架构
查看>>
集合体系
查看>>
vi命令提示:Terminal too wide
查看>>
nyoj 5 Binary String Matching(string)
查看>>
引用 移植Linux到s3c2410上
查看>>
BizTalk 2010 单机安装
查看>>
人与人之间的差距是从大学开始的
查看>>
vue 开发过程中遇到的问题
查看>>
[Swift]LeetCode341. 压平嵌套链表迭代器 | Flatten Nested List Iterator
查看>>