zoukankan      html  css  js  c++  java
  • [模板]点分治

    算法流程:找到树的重心,删去这个点,递归子树。
    题号luogu3806

    #include <iostream>
    #include <ctime>
    #include <algorithm>
    #include <windows.h>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=10005;
    inline int read(){
        int k=0,f=1; char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
        return k*f;
    }
    int n,m,K,siz[N],head[N],ecnt,size,rt,cnt,a[150],f[N];
    struct Edge{int to,nxt,val;}e[N<<1];
    struct Node{int from,val; bool operator < (const Node &rhs) const {return val<rhs.val;};};
    bool vis[N],ans[106];
    Node dis[10005];
    void add(int bg,int ed,int val){(++ecnt)[e].to=ed;ecnt[e].val=val;ecnt[e].nxt=bg[head];bg[head]=ecnt;}
    int binary(int x) {
    	int l=1,r=cnt,ans=0;
    	while(l<=r) {
    		int mid=l+r>>1;
    		if(dis[mid].val<x) l=mid+1;
    		else r=mid-1,ans=mid;
    	}
    	return ans;
    }
    void barycenter(int x,int fa) {
    	f[x]=0,siz[x]=1;
    	for(int i=head[x];i;i=e[i].nxt) {
    		int v=e[i].to;
    		if(vis[v]||fa==v) continue;
    		barycenter(v,x);
    		f[x]=max(f[x],siz[v]);
    		siz[x]+=siz[v];
    	}
    	f[x]=max(f[x],size-siz[x]);
    	if(f[x]<f[rt]) rt=x;
    }
    void dfs(int x,int fa,int from,int val) {
    	dis[++cnt]={from,val};
    	for(int i=head[x];i;i=e[i].nxt) {
    		int v=e[i].to;
    		if(vis[v]||fa==v) continue;
    		dfs(v,x,from,val+e[i].val);
    	}
    }
    void work(int x) {
    	cnt=0;
    	for(int i=x[head];i;i=i[e].nxt ) {
    		int v=i[e].to;
    		if(v[vis]) continue;
    		dfs(v,x,v,e[i].val);
    	}
    	(++cnt)[dis]={0,0};
    	sort(dis+1,dis+1+cnt);
    	for(int i=1;i<=m;i++) {
    		if(i[ans]) continue;
    		int l=1;
    		while(l<cnt&&a[i]>(dis[l].val+dis[cnt].val)) l++;
    		while(l<cnt&&!ans[i]) {
    			if(a[i]-dis[l].val<dis[l].val) break;
    			int pos=binary(a[i]-dis[l].val);
    			while(dis[pos].val+dis[l].val==a[i]&&l<=cnt&&dis[pos].from==dis[l].from) pos++;
    			if(dis[pos].val+dis[l].val==a[i]) ans[i]=1;
    			l++;
    		}
    	}
    }
    void solve(int x) {
    	vis[x]=1;
    	work(x);
    	for(int i=head[x];i;i=e[i].nxt) {
    		int v=e[i].to;rt=0;
    		if(v[vis]) continue;
    		siz[rt]=size=siz[v];
    		barycenter(v,0);
    		solve(rt);
    	}
    }
    int main() {
    	int st=clock();
    	n=read();m=read();
    	for(int i=1,x,y,z;i<n;i++) 	x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z);
    	for(int i=1;i<=m;i++) a[i]=read();
    	f[rt]=size=n;
    	barycenter(1,0);
    	solve(rt);
    	for(int i=1;i<=m;i++)puts(ans[i]?"AYE":"NAY");
    	int ed=clock();
    	Sleep(200);
    	cout<<ed-st;
    	return 0;
    }
    
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    ASP.NET(4):多语言的解决方案
    无题
    SIP 计时器的总结(转)
    一个Sip协议栈的实现方案
    通过拦截WCF消息进行身份栈传播
    从WPF控件拖放到Winform控件的注意事项
    一个用C#操作OpenLDAP的例子
    通过定制行为拦截WCF消息
    一个基于Prism的方案的介绍
    MVVM模式下附加属性的使用
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9475605.html
Copyright © 2011-2022 走看看