zoukankan      html  css  js  c++  java
  • bzoj 4326: NOIP2015 运输计划【树链剖分+二分+树上差分】

    常数巨大,lg上开o2才能A
    首先预处理出运输计划的长度len和lca,然后二分一个长度w,对于长度大于w的运输计划,在树上差分(d[u]+1,d[v]+1,d[lca]-2),然后dfs,找出所有覆盖所有边的边的边权最大值,然后用最长运输计划减去最大值看是否符合要求即可

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=600005;
    int n,m,h[N],cnt,si[N],hs[N],fa[N],va[N],de[N],id[N],rl[N],tot,fr[N],d[N],s[N],v[N];
    struct qwe
    {
    	int ne,to,va;
    }e[N];
    struct xds
    {
    	int l,r,s;
    }t[N<<1];
    struct ys
    {
    	int s,t,l,lc;
    }a[N];
    bool cmp(const ys &a,const ys &b)
    {
    	return a.l<b.l;
    }
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void add(int u,int v,int w)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	e[cnt].va=w;
    	h[u]=cnt;
    }
    void dfs1(int u,int fat)
    {
    	fa[u]=fat;
    	de[u]=de[fat]+1;
    	si[u]=1;
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fat)
    		{
    			dfs1(e[i].to,u);
    			si[u]+=si[e[i].to];
    			va[e[i].to]=e[i].va;
    			if(si[e[i].to]>si[hs[u]])
    				hs[u]=e[i].to;
    		}
    }
    void dfs2(int u,int top)
    {
    	fr[u]=top;
    	id[u]=++tot;
    	rl[tot]=u;
    	if(!hs[u])
    		return;
    	dfs2(hs[u],top);
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa[u]&&e[i].to!=hs[u])
    			dfs2(e[i].to,e[i].to);
    }
    int lca(int u,int v)
    {
    	for(;fr[u]!=fr[v];de[fr[u]]>de[fr[v]]?u=fa[fr[u]]:v=fa[fr[v]]);
    	return de[u]<de[v]?u:v;
    }
    void build(int ro,int l,int r)
    {
    	t[ro].l=l,t[ro].r=r;
    	if(l==r)
    	{
    		t[ro].s=va[rl[l]];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ro<<1,l,mid);
    	build(ro<<1|1,mid+1,r);
    	t[ro].s=t[ro<<1].s+t[ro<<1|1].s;
    }
    int ques(int ro,int l,int r)
    {
    	if(t[ro].l==l&&t[ro].r==r)
    		return t[ro].s;
    	int mid=(t[ro].l+t[ro].r)>>1;
    	if(r<=mid)
    		return ques(ro<<1,l,r);
    	else if(l>mid)
    		return ques(ro<<1|1,l,r);
    	else
    		return ques(ro<<1,l,mid)+ques(ro<<1|1,mid+1,r);
    }
    int wen(int u,int v)
    {
    	int r=0;
    	while(fr[u]!=fr[v])
    	{
    		if(de[fr[u]]<de[fr[v]])
    			swap(u,v);
    		r+=ques(1,id[fr[u]],id[u]);
    		u=fa[fr[u]];
    	}
    	if(u!=v)
    	{
    		if(de[u]>de[v])
    			swap(u,v);
    		r+=ques(1,id[u]+1,id[v]);
    	}
    	return r;
    }
    void dfs(int u,int fa)
    {
    	int x=v[u];
    	v[u]+=d[u];
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa)
    		{
    			dfs(e[i].to,u);
    			v[u]+=v[e[i].to];
    		}
    	s[u]=v[u]-x;
    }
    bool ok(int w)
    {
    	memset(d,0,sizeof(d));
    	memset(s,0,sizeof(s));
    	memset(v,0,sizeof(v));
    	int mx=0,con=0;
    	for(int i=m;i>=1&&a[i].l>w;i--)
    		d[a[i].s]++,d[a[i].t]++,d[a[i].lc]-=2,con++;
    	dfs(1,0);
    	for(int i=1;i<=n;i++)
    		if(s[i]==con)
    			mx=max(mx,va[i]);//,cerr<<i<<" ";cerr<<endl;//cerr<<w<<" "<<mx<<endl;
    	return a[m].l-mx<=w;
    }
    int main()
    {
    	n=read(),m=read();
    	for(int i=1;i<n;i++)
    	{
    		int x=read(),y=read(),z=read();
    		add(x,y,z),add(y,x,z);
    	}
    	dfs1(1,0);
    	dfs2(1,1);
    	build(1,1,n);
    	for(int i=1;i<=m;i++)
    		a[i].s=read(),a[i].t=read(),a[i].l=wen(a[i].s,a[i].t),a[i].lc=lca(a[i].s,a[i].t);//,cerr<<a[i].l<<endl;
    	// int x=a[1].s;
    	// while(x!=a[1].lc)
    	// {
    		// cerr<<x<<" "<<va[x]<<endl;
    		// x=fa[x];
    	// }
    	// cerr<<a[1].lc<<endl;
    	// x=a[1].t;
    	// while(x!=a[1].lc)
    	// {
    		// cerr<<x<<" "<<va[x]<<endl;
    		// x=fa[x];
    	// }
    	sort(a+1,a+1+m,cmp);//cerr<<"OK2"<<endl;
    	int l=0,r=1e9,ans;
    	while(l<=r)
    	{
    		int mid=(l+r)>>1;
    		if(ok(mid))
    			r=mid-1,ans=mid;
    		else
    			l=mid+1;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    upt:我怕不是个傻子……并不需要线段树

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=600005;
    int n,m,h[N],cnt,si[N],hs[N],fa[N],va[N],len[N],de[N],fr[N],d[N],s[N],v[N];
    struct qwe
    {
    	int ne,to,va;
    }e[N];
    struct ys
    {
    	int s,t,l,lc;
    }a[N];
    bool cmp(const ys &a,const ys &b)
    {
    	return a.l<b.l;
    }
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void add(int u,int v,int w)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	e[cnt].va=w;
    	h[u]=cnt;
    }
    void dfs1(int u,int fat)
    {
    	fa[u]=fat;
    	de[u]=de[fat]+1;
    	len[u]=len[fat]+va[u];
    	si[u]=1;
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fat)
    		{
    			va[e[i].to]=e[i].va;
    			dfs1(e[i].to,u);
    			si[u]+=si[e[i].to];
    			if(si[e[i].to]>si[hs[u]])
    				hs[u]=e[i].to;
    		}
    }
    void dfs2(int u,int top)
    {
    	fr[u]=top;
    	if(!hs[u])
    		return;
    	dfs2(hs[u],top);
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa[u]&&e[i].to!=hs[u])
    			dfs2(e[i].to,e[i].to);
    }
    int lca(int u,int v)
    {
    	for(;fr[u]!=fr[v];de[fr[u]]>de[fr[v]]?u=fa[fr[u]]:v=fa[fr[v]]);
    	return de[u]<de[v]?u:v;
    }
    void dfs(int u,int fa)
    {
    	int x=v[u];
    	v[u]+=d[u];
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa)
    		{
    			dfs(e[i].to,u);
    			v[u]+=v[e[i].to];
    		}
    	s[u]=v[u]-x;
    }
    bool ok(int w)
    {
    	memset(d,0,sizeof(d));
    	memset(s,0,sizeof(s));
    	memset(v,0,sizeof(v));
    	int mx=0,con=0;
    	for(int i=m;i>=1&&a[i].l>w;i--)
    		d[a[i].s]++,d[a[i].t]++,d[a[i].lc]-=2,con++;
    	dfs(1,0);
    	for(int i=1;i<=n;i++)
    		if(s[i]==con)
    			mx=max(mx,va[i]);//,cerr<<i<<" ";cerr<<endl;//cerr<<w<<" "<<mx<<endl;
    	return a[m].l-mx<=w;
    }
    int main()
    {
    	n=read(),m=read();
    	for(int i=1;i<n;i++)
    	{
    		int x=read(),y=read(),z=read();
    		add(x,y,z),add(y,x,z);
    	}
    	dfs1(1,0);
    	dfs2(1,1);
    	for(int i=1;i<=m;i++)
    		a[i].s=read(),a[i].t=read(),a[i].lc=lca(a[i].s,a[i].t),a[i].l=len[a[i].s]+len[a[i].t]-2*len[a[i].lc];//,cerr<<a[i].lc<<" "<<a[i].l<<endl;
    	// for(int i=1;i<=n;i++)
    		// cerr<<va[i]<<" "<<len[i]<<endl;
    	sort(a+1,a+1+m,cmp);
    	int l=0,r=1e9,ans;
    	while(l<=r)
    	{
    		int mid=(l+r)>>1;
    		if(ok(mid))
    			r=mid-1,ans=mid;
    		else
    			l=mid+1;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Leetcode 1489找到最小生成树李关键边和伪关键边
    Leetcode 113 路径总和 II
    hdu 1223 还是畅通工程
    hdu 1087 Super Jumping! Jumping! Jumping!
    hdu 1008 Elevator
    hdu 1037 Keep on Truckin'
    湖工oj 1241 畅通工程
    湖工oj 1162 大武汉局域网
    hdu 2057 A + B Again
    poj 2236 Wireless Network
  • 原文地址:https://www.cnblogs.com/lokiii/p/9383330.html
Copyright © 2011-2022 走看看