BZOJ 4326: NOIP2015 运输计划

来源:互联网 发布:dapaolu域名更换 编辑:程序博客网 时间:2024/06/05 13:33

去年这道题没做出来
然而今儿看到正解也是崩溃的
正解是个垃圾树剖。。
noip什么时候开始考树剖了???
好吧去年联赛的时候还没学树剖。。。


第一遍dfs除了处理那些个节点的重量外顺便处理下每个节点到根的距离
其他和普通树剖没什么区别
然后读入点对,先算出每一对的lca和距离,记下最大距离
二分答案,因为最长的那条路线是肯定要变短的,所以二分的上界就是最长的那条
对于一个答案,一个点对的距离如果大于这个数就在线段树上覆盖一次,最后每一条边统计覆盖次数,并找出覆盖次数等于距离大于答案的点对个数的最长的一条边,然后判断最长那条是否小于等于答案加该边长
覆盖什么的和树剖路径上修改的一样


本以为要调很久没想到一下就过了
本来1A的然而我文件没关T了一次。。。mdzz
去掉文件就直接过了。。

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define g getchar()#define ll long long#define inf 0x3f3f3f3f#define maxn 300010using namespace std;inline ll read(){    ll x=0,f=1;char ch=g;    for(;ch<'0'||ch>'9';ch=g)if(ch=='-')f=-1;    for(;ch>='0'&&ch<='9';ch=g)x=x*10+ch-'0';    return x*f;}inline void out(ll x){    int a[25],t=0;    if(x<0)putchar('-'),x=-x;    for(;x;x/=10)a[++t]=x%10;    for(int i=t;i;--i)putchar('0'+a[i]);    if(t==0)putchar('0');    putchar('\n');}struct re{int v,w,next;}ed[maxn*2];int e,cnt,m,n,mx,lca[maxn],x[maxn],y[maxn],ans;int sz[maxn],head[maxn],f[maxn],dis[maxn],bl[maxn],id[maxn],num[maxn],t[3*maxn],dist[maxn];inline void ins(int x,int y,int w){ed[++e]=(re){y,w,head[x]};head[x]=e;}void dfs1(int x){    sz[x]=1;    for(int i=head[x];i;i=ed[i].next)    if(ed[i].v!=f[x]){        f[ed[i].v]=x;dis[ed[i].v]=dis[x]+ed[i].w;        dfs1(ed[i].v);sz[x]+=sz[ed[i].v];    }}void dfs2(int x,int chain){    int now=0;bl[x]=chain;id[x]=++cnt;num[cnt]=x;    for(int i=head[x];i;i=ed[i].next)if(ed[i].v!=f[x]&&sz[now]<sz[ed[i].v])now=ed[i].v;    if(now)dfs2(now,chain);    for(int i=head[x];i;i=ed[i].next)if(ed[i].v!=now&&ed[i].v!=f[x])dfs2(ed[i].v,ed[i].v);}int lc(int x,int y){    int fx=bl[x],fy=bl[y];    for(;fx!=fy;){        if(dis[fx]<dis[fy])swap(x,y),swap(fx,fy);        x=f[fx];fx=bl[x];    }    return dis[x]<dis[y]?x:y;}inline void push(int k,int l,int r){if(l>=r)return;t[k<<1]+=t[k],t[k<<1|1]+=t[k];t[k]=0;}int query(int k,int l,int r,int cnt){    push(k,l,r);    if(l>r)return 0;    if(l==r)return t[k]==cnt?dis[num[l]]-dis[f[num[l]]]:0;    int mid=(l+r)>>1;    return max(query(k<<1,l,mid,cnt),query(k<<1|1,mid+1,r,cnt));}void add(int k,int l,int r,int x,int y){    if(x>y)return;    if(l==x&&r==y){++t[k];return;}    push(k,l,r);    int mid=(l+r)>>1;    if(mid>=x)add(k<<1,l,mid,x,min(mid,y));    if(mid<y)add(k<<1|1,mid+1,r,max(x,mid+1),y);}void clear(int k,int l,int r){    t[k]=0;if(l==r)return;int mid=(l+r)>>1;clear(k<<1,l,mid);clear(k<<1|1,mid+1,r);}void add(int x,int y){    for(;bl[x]!=bl[y];){        add(1,1,n,id[bl[y]],id[y]);        y=f[bl[y]];    }    add(1,1,n,id[x]+1,id[y]);}bool check(int t){    int mx=0,cnt=0;clear(1,1,n);    for(int i=1;i<=m;++i){        if(t<dist[i])        add(lca[i],x[i]),        add(lca[i],y[i]),        mx=max(mx,dist[i]),++cnt;    }    int ans=-query(1,1,n,cnt);    return mx+ans<=t;}int main(){    n=read();m=read();    for(int i=1;i<n;++i){        int x=read(),y=read(),w=read();        ins(x,y,w);ins(y,x,w);    }    dfs1(1);dfs2(1,1);    for(int i=1;i<=m;++i){        x[i]=read(),y[i]=read(),lca[i]=lc(x[i],y[i]);        dist[i]=dis[x[i]]+dis[y[i]]-2*dis[lca[i]];        mx=max(dist[i],mx);    }    int l=0,r=mx;    for(;l<=r;){        int mid=(l+r)>>1;        if(mid==11){            mid=0;            mid=11;        }        if(check(mid))ans=mid,r=mid-1;        else l=mid+1;    }    out(ans);    return 0;}
0 0
原创粉丝点击