Bzoj-3252: 攻略(贪心+DFS序+线段树)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3252

(其实我也在看只有神知道的世界,所以就来写这道题了。。。)

这道题解法题目里面都说了一半了QaQ...首先,很容易可以确定每次贪心取最大的一条路径,然后修改权值的正确性,(反证法:假如该贪心不正确,则存在两条路径p1,p2,权值和s(p1)>s(p2),先取p2比先取p1更优,那么,如果当前取的是最后一条路径,那么明显这个情况不成立,如果不是,则先取p2再取p1等效于先取p1再取p2,所以贪心成立)。

实现方法:

暴力当然TLE,我们可以把该树处理成DFS序,每个节点拆成在DFS中入栈的位置和出栈的位置,如,样例的一个DFS序就是: 1 2 3 3 4 4 2 5 5 1

然后,对于某个节点,在第一次出现的位置+w[i],最后出现的位置-w[i],然后进行一次求和sum[i]=sigma(a[j])(0<j<=i),那么,每次取最大的前缀和恰好就是最大的路径和。

修改:考虑到某个节点的权值变动,会影响到DFS序列中的后面的所有前缀和,所以每次修改时就用带懒惰标记的线段树来维护就可以了。

代码(记得开long long):

(速度还是一如既往的渣:)

e61190ef76c6a7ef0d2e5a3cfffaaf51f3de66a4.jpg.png
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define MAXN 200010
#define AddEdge(s,t) Add(s,t),Add(t,s)
#define L(t) T[t].l
#define R(t) T[t].r
#define D(t) T[t].delta
#define M(t) T[t].Max
#define Mm(t) T[t].maxm
struct edge{
    int t;
    edge *next;
    edge (){
        next=NULL;
    }
}*head[MAXN];
void Add(int s,int t){
    edge *p=new(edge);
    p->t=t,p->next=head[s];
    head[s]=p;
}
int fir[MAXN],las[MAXN],fat[MAXN],n,k;
long long sum[MAXN*2],w[MAXN];
int c[MAXN*2];
bool f[MAXN];
int Index=0;
void dfs(int v){
    f[v]=false;
    sum[fir[v]=++Index]=w[v];
    c[Index]=v;
    for(edge *p=head[v];p;p=p->next)if(f[p->t]){
        fat[p->t]=v;
        dfs(p->t);
    }
    sum[las[v]=++Index]=-w[v];
    c[Index]=v;
}
struct node{
    int l,r,maxm;
    long long Max,delta;
    node (){
        delta=0;
    }
} T[MAXN*10];
void pushdown(int t){
    if(D(t)){
        M(t)+=D(t);
        if(L(t)<R(t)){
            D(t<<1)+=D(t),D((t<<1)^1)+=D(t);
        }
        D(t)=0;
    }
}
void update(int t){
    pushdown(t);
    if(L(t)<R(t)){
        pushdown(t<<1),pushdown((t<<1)^1);
        if(M(t<<1)>M((t<<1)^1)){
            M(t)=M(t<<1),Mm(t)=Mm(t<<1);
        }else{
            M(t)=M((t<<1)^1),Mm(t)=Mm((t<<1)^1);
        }
    }
}
void Build(int l,int r,int t){
    L(t)=l,R(t)=r;
    if(l==r){
        M(t)=sum[l],Mm(t)=l;
        return;
    }
    int mid=(l+r)>>1;
    Build(l,mid,t<<1),Build(mid+1,r,(t<<1)^1);
    update(t);
}
void Change(int l,int r,int t,long long del){
    if(L(t)==l&&R(t)==r){
        D(t)+=del;
        pushdown(t);
        return;
    }
    pushdown(t);
    int mid=(L(t)+R(t))>>1;
    if(mid>=r) Change(l,r,t<<1,del)  
    ;  else if(mid<l) Change(l,r,(t<<1)^1,del)
    ;  else Change(l,mid,t<<1,del),Change(mid+1,r,(t<<1)^1,del);
    update(t);
}
int main(){
    scanf("%d%d",&n,&k);
    for(int i=0;i++<n;) scanf("%lld",&w[i]);
    memset(head,0,sizeof(head));
    for(int i=0;i++<n-1;){
        int s,t;
        scanf("%d%d",&s,&t);
        AddEdge(s,t);
    }
    memset(f,true,sizeof(f));
    fat[1]=0;
    sum[0]=0;
    dfs(1);
    for(int i=0;i++<2*n;) sum[i]+=sum[i-1];
    Build(1,2*n,1);
    memset(f,true,sizeof(f));
    f[0]=false;
    long long ans=0;
    while(k--){
        ans+=M(1);
        int v=c[Mm(1)];
        while(f[v]){
            f[v]=false;
            Change(fir[v],2*n,1,-w[v]);
            Change(las[v],2*n,1,w[v]);
            v=fat[v];
        }
    }
    printf("%lld\n",ans);
    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容