zoukankan      html  css  js  c++  java
  • P4178 Tree 点分治

    思路:点分治

    提交:1次

    题解:

    要求权值和(leq K) 的路径,我们可以类比点分治的模板,把长为(len)是否存在,改为(len)的路径的条数,并用用树状数组维护前缀和,这样就可以求出答案。

    代码:

    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    template<class I>	inline I g(I& x) { x=0; register I f=1;
    	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
    } const int N=40010,Inf=1e9;
    int n,m,cnt,tot,SZ,rt,sum,ans,K; bool vis[N];
    int vr[N<<1],nxt[N<<1],w[N<<1],fir[N],d[N],sz[N],mx[N],dis[N],buf[N];
    namespace BIT {
    const int LIM=20000000;
    int c[LIM+10];
    inline void add(int p,int d) {for(;p<=LIM;p+=p&-p) c[p]+=d;}
    inline int query(int p) { R ret=0;
    	for(;p;p-=p&-p) ret+=c[p]; return ret;
    }
    }
    inline void add(int u,int v,int ww) {
    	vr[++cnt]=v,nxt[cnt]=fir[u],w[cnt]=ww,fir[u]=cnt;
    	vr[++cnt]=u,nxt[cnt]=fir[v],w[cnt]=ww,fir[v]=cnt;
    }
    inline void getsz(int u,int fa) { 
    	sz[u]=1,mx[u]=0; for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
    		if(vis[v]||v==fa) continue;
    		getsz(v,u),sz[u]+=sz[v];
    		mx[u]=max(mx[u],sz[v]);
    	} mx[u]=max(mx[u],sum-sz[u]);
    	if(mx[u]<mx[rt]) rt=u;
    }
    inline void getdis(int u,int fa) { dis[++tot]=d[u];
    	for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
    		if(vis[v]||v==fa) continue;
    		d[v]=d[u]+w[i],getdis(v,u);
    	}
    }
    inline void solve(int u,int fa) { 
    	SZ=0,BIT::add(1,1),buf[++SZ]=0,vis[u]=true;
    	for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
    		if(v==fa||vis[v]) continue;
    		d[v]=w[i]; getdis(v,u);
    		for(R k=1;k<=tot;++k) if(K>=dis[k]) ans+=BIT::query(K-dis[k]+1);
    		for(R k=1;k<=tot;++k) buf[++SZ]=dis[k],BIT::add(dis[k]+1,1);
    		tot=0;
    	} while(SZ) BIT::add(buf[SZ]+1,-1),--SZ;
    	for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
    		if(v==fa||vis[v]) continue;
    		sum=sz[v]; rt=0,mx[0]=Inf;
    		getsz(v,u),getsz(rt,-1); solve(rt,u);
    	}
    }
    inline void main() {
    	g(n); for(R i=1,u,v,w;i<n;++i) g(u),g(v),g(w),add(u,v,w);
    	g(K); sum=n,mx[0]=Inf; getsz(1,-1),getsz(rt,-1);
    	solve(rt,-1); printf("%d
    ",ans);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2019.08.31
    69

  • 相关阅读:
    PHP header函数使用教程
    mysql show processlist 命令检查mysql lock
    MySQL
    background-position 用法详细介绍
    Windows下Mysql主从配置(Mysql5.5)
    Tcl介绍和基础语法
    研发项目管理
    VCS 查看代码覆盖率
    Openrisc的or1200
    MY $MYVIMRC
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11437891.html
Copyright © 2011-2022 走看看