1. 程式人生 > >【noip】2016 運輸計劃

【noip】2016 運輸計劃

可以使用樹剖 nlog^2n 卡常後能過 就是碼量有點大

#include<bits/stdc++.h>
#define R register

using namespace std;
const int maxn=3e5+5;
char *P;
void QREAD()
{
    static char buf[1<<25];P=&buf[0];
    fread(buf,1,1<<25,stdin);
}

char get_char()
{
    return *(P++);
}

void readint(int &x)
{
    char ch=get_char();int f=1;x=0;
    for(;;)
    {
        if(ch=='-')f=-1;
        if(ch<'0'||ch>'9');
        else break;
        ch=get_char();
    }
    for(;;)
    {
        if(ch<'0'||ch>'9')break;
        x*=10;x+=ch-'0';
        ch=get_char();
    }x*=f;
}

struct rmq
{
    int t[maxn<<2],lazy[maxn<<2];
    void pushup(int x){t[x]=max(t[x<<1],t[x<<1|1]);}
    void pushdown(int x)
    {
        if(lazy[x]==0)return ;
        lazy[x<<1]=max(lazy[x<<1],lazy[x]);
        lazy[x<<1|1]=max(lazy[x<<1|1],lazy[x]);
        t[x<<1]=max(t[x<<1],lazy[x<<1]);
        t[x<<1|1]=max(t[x<<1|1],lazy[x<<1|1]);
    }
    void modify(int ql,int qr,int l,int r,int x,int val)
    {
        if(ql>qr)return;
        if(ql<=l&&r<=qr)
        {
            t[x]=max(t[x],val);lazy[x]=max(lazy[x],val);
            return ;
        }
        int m=(l+r)>>1;
        pushdown(x);
        if(ql<=m)modify(ql,qr,l,m,x<<1,val);
        if(m<qr)modify(ql,qr,m+1,r,x<<1|1,val);
        pushup(x);
    }
    int query(int ql,int qr,int l,int r,int x)
    {
        if(ql>qr)return -1;
        if(ql<=l&&r<=qr)return t[x];
        int m=(l+r)>>1,ret=-1;
        pushdown(x);
        if(ql<=m)ret=max(ret,query(ql,qr,l,m,x<<1));
        if(m<qr)ret=max(ret,query(ql,qr,m+1,r,x<<1|1));
        return ret;
    }
}T;

struct segtreesum
{
    int t[maxn<<2],lazy[maxn<<2];
    void pushup(int x){t[x]=t[x<<1]+t[x<<1|1];}
    void pushdown(int x,int ls,int rs)
    {
        if(lazy[x]==0)return ;
        t[x<<1]+=lazy[x]*ls;t[x<<1|1]+=lazy[x]*rs;
        lazy[x<<1]+=lazy[x];lazy[x<<1|1]+=lazy[x];
        lazy[x]=0;
    }
    void modify(int ql,int qr,int l,int r,int x,int val)
    {
        if(ql>qr)return;
        if(ql<=l&&r<=qr)
        {
            t[x]+=val;lazy[x]+=val;
            return ;
        }
        int m=(l+r)>>1;
        pushdown(x,m-l+1,r-m);
        if(ql<=m)modify(ql,qr,l,m,x<<1,val);
        if(m<qr)modify(ql,qr,m+1,r,x<<1|1,val);
        pushup(x);
    }
    int query(int ql,int qr,int l,int r,int x)
    {
        if(ql>qr)return 0;
        if(ql<=l&&r<=qr)return t[x];
        int m=(l+r)>>1,ret=0;
        pushdown(x,m-l+1,r-m);
        if(ql<=m)ret+=query(ql,qr,l,m,x<<1);
        if(m<qr)ret+=query(ql,qr,m+1,r,x<<1|1);
        return ret;
    }
}t;

struct Edge
{
    int to,val,nxt;
}edge[maxn<<2];int EC;
int head[maxn];
void add(int a,int b,int t)
{
    ++EC;
    edge[EC].nxt=head[a];edge[EC].to=b;edge[EC].val=t;head[a]=EC;
}

int n,m;
void read()
{
    readint(n);readint(m);
    for(R int i=1; i<n; i++)
    {
        R int a,b,t;
        readint(a);readint(b);readint(t);
        add(a,b,t);
        add(b,a,t);
    }
}

int mson[maxn],dep[maxn],sz[maxn],fa[maxn];
void dfs1(int x,int f)
{
    dep[x]=dep[f]+1;sz[x]=1;fa[x]=f;
    for(R int i=head[x];i!=0; i=edge[i].nxt)
    {
        int to=edge[i].to;
        if(to==f)continue;
        dfs1(to,x);
        if(mson[x]==0)mson[x]=to;else if(sz[mson[x]]<sz[to])mson[x]=to;
        sz[x]+=sz[to];
    }
}
int id[maxn],cnt=0,top[maxn];
void dfs2(int x,int tp)
{
    ++cnt;id[x]=cnt;top[x]=tp;
    if(!mson[x])return ;
    dfs2(mson[x],tp);
    for(R int i=head[x]; i!=0; i=edge[i].nxt)
    {
        int to=edge[i].to;
        if(to==fa[x]||to==mson[x])continue;
        dfs2(to,to);
    }
}

int elen[maxn];
void count(int x,int tl)
{
    //和普通點權不同的是,對於一顆樹來說,每一個點的點權被定義為他的父親到他的邊權
    //邊轉點 
    elen[id[x]]=tl;
    if(x!=1)
    {
        t.modify(id[x],id[x],1,n,1,tl);
    }
    for(R int i=head[x];i!=0;i=edge[i].nxt)
    {
        int to=edge[i].to,val=edge[i].val;
        if(to==fa[x])continue;
        count(to,val);
    }
}

int ask(int u,int v)
{
    R int ret=0;
    while(top[u]!=top[v])
    {
        if(dep[top[u]]>dep[top[v]])swap(u,v);
        ret+=t.query(id[top[v]],id[v],1,n,1);
        v=fa[top[v]];
    }
    if(dep[u]>dep[v])swap(u,v);
    ret+=t.query(id[u]+1,id[v],1,n,1);
    return ret;
}

int ans,ori;

void go(int u,int v)
{
    while(top[u]!=top[v])
    {
        if(dep[top[u]]>dep[top[v]])swap(u,v);
        ans=min(ans,max(ori-elen[id[v]],T.query(id[v],id[v],1,n,1)));
        v=fa[v];
    }
    if(dep[u]>dep[v])swap(u,v);
    while(u!=v)
    {
        ans=min(ans,max(ori-elen[id[v]],T.query(id[v],id[v],1,n,1)));
        v=fa[v];
    }
}

vector<pair<int,int> >chain[maxn];int csz;

void makechain(int u,int v)
{
    while(top[u]!=top[v])
    {
        if(dep[top[u]]>dep[top[v]])swap(u,v);
        int st=id[top[v]],ed=id[v];
        if(st<=ed)chain[csz].push_back(make_pair(st,ed));
        v=fa[top[v]];
    }
    if(dep[u]>dep[v])swap(u,v);
    int st=id[u]+1,ed=id[v];if(st<=ed)chain[csz].push_back(make_pair(st,ed));
    csz++;
}

vector<pair<int,int> >query;
vector<int>qans;
int mem;

void prepare()
{
    dfs1(1,1);
    dfs2(1,1);
    count(1,1);
}
void solve()
{
    prepare();
    ans=-1;
    for(R int i=1;i<=m;i++)
    {
        R int u,v;readint(u);readint(v);
        query.push_back(make_pair(u,v));
        makechain(u,v);
        int len=ask(u,v);qans.push_back(len);
        if(len>ans)ans=len,mem=i-1;
    }
    ori=ans;
    for(R int i=0;i<csz;i++)
    {
        sort(chain[i].begin(),chain[i].end());
        int st=1;
        for(int j=0;j<(int)chain[i].size();j++)
        {
            T.modify(st,chain[i][j].first-1,1,n,1,qans[i]);
            st=chain[i][j].second+1;
        }
        T.modify(st,n,1,n,1,qans[i]);
    }
    go(query[mem].first,query[mem].second);
    printf("%d\n",ans);
}

int main()
{
    QREAD();
    read();
    solve();
    return 0;
}