【noip】2016 運輸計劃
阿新 • • 發佈:2018-12-15
可以使用樹剖 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; }