• dfs序+线段树 BZOJ3252 攻略


    3252: 攻略

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 496  Solved: 211
    [Submit][Status][Discuss]

    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

    dfs序+线段树的模板吧……

    函数传参不要写错!!!!!!

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 #define inf 1000000000000000ll 
      7 int n,k,cnt,tot;
      8 long long ans;
      9 long long val[200010],sum[200010];
     10 int head[200010],getin[200010],getout[200010],oula[200010],fa[200010];
     11 bool check[200010];
     12 struct data{
     13     int next,to;
     14 }edge[400010];
     15 struct dt{
     16     long long mx,loc,tag;
     17 }segtree[800010]; 
     18 void add(int start,int end){
     19     edge[++cnt].next=head[start];
     20     edge[cnt].to=end;
     21     head[start]=cnt;
     22     fa[end]=start;
     23 }
     24 void dfs(int u){
     25     getin[u]=++tot;
     26     oula[tot]=u;
     27     for(int i=head[u];i;i=edge[i].next){
     28         sum[edge[i].to]=sum[u]+val[edge[i].to];
     29         dfs(edge[i].to);
     30     }
     31     getout[u]=tot;
     32 }
     33 void up(int pos){
     34     segtree[pos].mx=0;
     35     if(segtree[pos<<1].mx>segtree[pos].mx){
     36         segtree[pos].mx=segtree[pos<<1].mx;
     37         segtree[pos].loc=segtree[pos<<1].loc;
     38     }
     39     if(segtree[pos<<1|1].mx>segtree[pos].mx){
     40         segtree[pos].mx=segtree[pos<<1|1].mx;
     41         segtree[pos].loc=segtree[pos<<1|1].loc;       
     42     }
     43 }
     44 void build(int pos,int ll,int rr){
     45     if(ll==rr){
     46         segtree[pos].mx=sum[oula[ll]];
     47         segtree[pos].loc=ll;
     48         return;
     49     }
     50     int mid=(ll+rr)>>1;
     51     build(pos<<1,ll,mid);
     52     build(pos<<1|1,mid+1,rr);
     53     up(pos);
     54 }
     55 void update(int pos,long long dd){//!!!!!!!!!!!!!!!!!!!!!!!! long long
     56     segtree[pos].mx-=dd;
     57     segtree[pos].tag+=dd;
     58 }
     59 void down(int pos){
     60     if(!segtree[pos].tag) return;
     61     update(pos<<1,segtree[pos].tag);
     62     update(pos<<1|1,segtree[pos].tag);
     63     segtree[pos].tag=0;
     64     return;
     65 }
     66 void change(int pl,int pr,long long dd,int pos,int ll,int rr){
     67     int mid=(ll+rr)>>1;
     68     if(pl>rr||pr<ll) return;
     69     if(pl<=ll&&pr>=rr){
     70         update(pos,dd);
     71         return;
     72     }
     73     down(pos);
     74     if(pr<=mid) change(pl,pr,dd,pos<<1,ll,mid);
     75     else if(pl>mid) change(pl,pr,dd,pos<<1|1,mid+1,rr);
     76     else{
     77         change(pl,mid,dd,pos<<1,ll,mid);
     78         change(mid+1,pr,dd,pos<<1|1,mid+1,rr);
     79     }
     80     up(pos);
     81 }
     82 int main(){
     83     scanf("%d%d",&n,&k);
     84     for(int i=1;i<=n;i++) scanf("%lld",&val[i]);
     85     int x,y;
     86     for(int i=1;i<n;i++){
     87         scanf("%d%d",&x,&y);
     88         add(x,y);
     89     }
     90     sum[1]=val[1];
     91     dfs(1);
     92     build(1,1,n);
     93     for(int i=1;i<=k;i++){
     94         ans+=segtree[1].mx;
     95         for(int j=oula[segtree[1].loc];!check[j]&&j;j=fa[j]){
     96             check[j]=1;
     97             change(getin[j],getin[j],inf,1,1,n);//ll的极值??? 
     98             if(getin[j]<getout[j]) change(getin[j]+1,getout[j],val[j],1,1,n);
     99         }
    100     }
    101     printf("%lld",ans);
    102     return 0;
    103 }
  • 相关阅读:
    leetcode hot 100- 84. 柱状图中最大的矩形
    leetcode hot 100- 221. 最大正方形
    leetcode hot 100-34. 在排序数组中查找元素的第一个和最后一个位置
    leetcode hot 100-剑指 Offer 37. 序列化二叉树
    leetcode hot 100-2. 两数相加
    leetcode hot 100-33. 搜索旋转排序数组
    leetcode hot 100- 98. 验证二叉搜索树
    leetcode hot 100-152. 乘积最大子数组
    leetcode hot 100-19. 删除链表的倒数第N个节点
    v-modal的使用。
  • 原文地址:https://www.cnblogs.com/zwube/p/7048957.html
Copyright © 2020-2023  润新知