zoukankan      html  css  js  c++  java
  • [NOIP2015]运输计划 线段树or差分二分

    [NOIP2015]运输计划

    链接

    luogu
    好久没写博客了,水一篇波。

    思路1 暴力数据结构

    枚举最长链的边,删除后代价为(最长链-边权,不经过这条边的链)的最大值。
    不经过某条边的最大值要用线段树维护补集。
    复杂度(O(nlog^2n))

    思路2 二分树上差分

    二分答案,删除的边为(>mid)的链的交集。
    用树上查分维护交集。
    最后在交集中找个最大的边删除就好了。
    复杂度(O(nlogn))

    总的

    思路2,复杂度小,好写,简单,细节少。
    思路1,复杂度高,码量大,细节多,并不是呢么好想。
    所以并不是很建议写第一种。
    但他靠着树剖的小常数跑过了树上差分(至少我是这样,1.9s->1.2s)。

    代码1

    #include <bits/stdc++.h>
    using namespace std;
    const int _=5e5+7;
    int read() {
    	int x=0,f=1;char s=getchar();
    	for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    	for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    	return x*f;
    }
    int n,m,ans,u[_],v[_],dsr[_],w[_];
    struct node {
    	int v,nxt,q,w;
    }e[_<<1];
    int head[_],tot;
    void add(int u,int v,int q) {
    	e[++tot].v=v;
    	e[tot].q=q;
    	e[tot].nxt=head[u];
    	head[u]=tot;
    }
    int f[_],dep[_],siz[_],son[_],top[_],idx[_],dis[_],nb[_],cnt;
    void dfs1(int u,int fa) {
    	dep[u]=dep[fa]+1;
    	f[u]=fa;
    	siz[u]=1;
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(v==fa) continue;
    		w[v]=e[i].q;
    		dis[v]=dis[u]+e[i].q;
    		dfs1(v,u);
    		siz[u]+=siz[v];
    		if(siz[son[u]]<siz[v]) son[u]=v;
    	}
    }
    void dfs2(int u,int topf) {
    	top[u]=topf;
    	idx[u]=++cnt;
    	nb[cnt]=u;
    	if(!son[u]) return;
    	dfs2(son[u],topf);
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(!idx[v]) dfs2(v,v);
    	}
    }
    namespace seg_tree {
    	#define ls rt<<1
    	#define rs rt<<1|1
    	int ma[_<<2],lazy[_];
    	void tag(int rt,int val) {ma[rt]=max(ma[rt],val);lazy[rt]=max(lazy[rt],val);}
    	void pushdown(int rt) {tag(ls,lazy[rt]);tag(rs,lazy[rt]);}
    	void modify(int L,int R,int val,int l,int r,int rt) {
    		if(L>R) return;
    		if(L<=l&&r<=R) return tag(rt,val);
    		int mid=(l+r)>>1;
    		pushdown(rt);
    		if(L<=mid) modify(L,R,val,l,mid,ls);
    		if(R>mid) modify(L,R,val,mid+1,r,rs);
    		ma[rt]=max(ma[ls],ma[rs]);
    	}
    	void dfs(int l,int r,int rt) {
    		if(l==r) return void(dsr[nb[l]]=ma[rt]);
    		int mid=(l+r)>>1;
    		pushdown(rt);
    		if(l<=mid) dfs(l,mid,ls);
    		if(r>mid) dfs(mid+1,r,rs);
    	}
    }
    int lca(int x,int y) {
    	while(top[x]!=top[y]) {
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		x=f[top[x]];
    	} return dep[x]<dep[y]?x:y;
    }
    void QQ(int x,int y,int val) {
    	int las=n;
    	while(top[x]!=top[y]) {
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		seg_tree::modify(idx[x]+1,las,val,1,n,1);
    		las=idx[top[x]]-1;
    		x=f[top[x]];
    	}
    	if(dep[x]<dep[y]) swap(x,y);
    	seg_tree::modify(idx[x]+1,las,val,1,n,1);
    	seg_tree::modify(1,idx[y],val,1,n,1);
    }
    int main() {
    	n=read(),m=read();
    	for(int i=1,x,y,q;i<n;++i) {
    		x=read(),y=read(),q=read();
    		add(x,y,q),add(y,x,q);
    	}
    	for(int i=1;i<=m;++i) {
    		u[i]=read(),v[i]=read();
    		if(u[i]==v[i]) m--,i--;
    	}
    	dfs1(1,0),dfs2(1,1);
    	int id=0,ma=0;
    	for(int i=1;i<=m;++i) {
    		int val=dis[u[i]]+dis[v[i]]-2*dis[lca(u[i],v[i])];
    		QQ(u[i],v[i],val);
    		if(ma<val) id=i,ma=val;
    	}
    	if(!id) return printf("0
    "),0;
    	seg_tree::dfs(1,n,1);
    	int x=u[id],y=v[id],ans=0x3f3f3f3f;
    	while(x!=y) {
    		if(dep[x]<dep[y]) swap(x,y);
    		ans=min(ans,max(dsr[x],ma-w[x]));
    		x=f[x];
    	}
    	cout<<ans<<"
    ";
    	return 0;
    }
    

    代码2

    #include <bits/stdc++.h>
    using namespace std;
    const int _=5e5+7;
    int read() {
    	int x=0,f=1;char s=getchar();
    	for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    	for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    	return x*f;
    }
    int n,m,ans,u[_],v[_],LCA[_],len[_],the_biggest,w[_];
    struct node {
    	int v,nxt,q;
    }e[_<<1];
    int head[_],tot;
    void add(int u,int v,int q) {
    	e[++tot].v=v;
    	e[tot].q=q;
    	e[tot].nxt=head[u];
    	head[u]=tot;
    }
    int f[_],dep[_],siz[_],son[_],dis[_],top[_],cnt;
    void dfs1(int u,int fa) {
    	dep[u]=dep[fa]+1,f[u]=fa,siz[u]=1;
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(v==fa) continue;
    		w[v]=e[i].q;
    		dis[v]=dis[u]+e[i].q;
    		dfs1(v,u);
    		siz[u]+=siz[v];
    		if(siz[son[u]]<siz[v]) son[u]=v;
    	}
    }
    void dfs2(int u,int topf) {
    	top[u]=topf;
    	if(!son[u]) return;
    	dfs2(son[u],topf);
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(!top[v]) dfs2(v,v);
    	}
    }
    int lca(int x,int y) {
    	while(top[x]!=top[y]) {
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		x=f[top[x]];
    	} return dep[x]<dep[y]?x:y;
    }
    int dsr[_],js;
    void dfs(int u,int fa) {
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(v==fa) continue;
    		dfs(v,u);
    		dsr[u]+=dsr[v];
    	}
    }
    bool check(int mid) {
    	js=0;
    	for(int i=0;i<=n;++i) dsr[i]=0;
    	for(int i=1;i<=m;++i) {
    		if(len[i]<=mid) continue;
    		dsr[LCA[i]]-=2;
    		dsr[u[i]]++;
    		dsr[v[i]]++;
    		++js;
    	}
    	dfs(1,0);
    	int ma=0x3f3f3f3f;
    	for(int i=1;i<=n;++i)
    		if(dsr[i]==js) ma=min(ma,the_biggest-w[i]);
    	return ma<=mid;
    }
    int main() {
    	n=read(),m=read();
    	for(int i=1,x,y,q;i<n;++i) {
    		x=read(),y=read(),q=read();
    		add(x,y,q),add(y,x,q);
    	}
    	dfs1(1,0),dfs2(1,1);
    	for(int i=1;i<=m;++i) {
    		u[i]=read(),v[i]=read(),LCA[i]=lca(u[i],v[i]);
    		len[i]=dis[u[i]]+dis[v[i]]-2*dis[LCA[i]];
    		the_biggest=max(the_biggest,len[i]);
    	}
    	int l=0,r=the_biggest,ans=0;
    	while(l<=r) {
    		int mid=(l+r)>>1;
    		if(check(mid)) ans=mid,r=mid-1;
    		else l=mid+1;
    	} cout<<ans<<"
    ";
    	return 0;
    }
    
  • 相关阅读:
    各种有趣言论收集
    人类未来进化方向恶考
    mysql 列所有表行数
    恩,有那么一个人
    00后厉害哇
    。。。。
    放弃微博,继续回来写月经
    嘿,大家还好吗
    git
    require js
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/11632097.html
Copyright © 2011-2022 走看看