zoukankan      html  css  js  c++  java
  • BZOJ1316 树上的询问

    题目传送门

    分析:
    点分治板题,对于每个重心,set维护每个子树里面的路径,然后每添加一棵子树的值之前,询问一下set里面是否有Len-dis[i]即可
    找到了就不做了,可以变很快
    注意询问的Len可能为0

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<set>
    
    #define maxn 20005
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n,q,K,rt,N;
    int fir[maxn],nxt[maxn],to[maxn],len[maxn],cnt;
    int qq[maxn];
    int sz[maxn];
    bool vis[maxn];
    int a[maxn],cur,dis[maxn];
    set<int>S;
    set<int>::iterator it;
    bool ans[maxn];
    
    inline void newnode(int u,int v,int w)
    {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,len[cnt]=w;}
    
    inline void getrt(int u,int fa)
    {
    	sz[u]=1;
    	int mx=0;
    	for(int i=fir[u];i;i=nxt[i])
    		if(to[i]!=fa&&!vis[to[i]])
    		{
    			getrt(to[i],u);
    			sz[u]+=sz[to[i]];
    			mx=max(mx,sz[to[i]]);
    		}
    	mx=max(mx,N-sz[u]);
    	if(mx<=N/2)rt=u;
    }
    
    inline void dfs(int u,int fa)
    {
    	sz[u]=1;
    	for(int i=fir[u];i;i=nxt[i])
    		if(to[i]!=fa&&!vis[to[i]])
    			dfs(to[i],u),sz[u]+=sz[to[i]];
    }
    
    inline void cal(int rt)
    {
    	S.clear();S.insert(0);
    	for(int i=fir[rt];i;i=nxt[i])
    		if(!vis[to[i]])
    		{
    			cur=0;
    			queue<int>Q;
    			dis[to[i]]=len[i];
    			Q.push(to[i]);a[++cur]=dis[to[i]];
    			while(!Q.empty())
    			{
    				int u=Q.front();Q.pop();
    				for(int j=fir[u];j;j=nxt[j])
    					if(sz[u]>sz[to[j]])
    						dis[to[j]]=dis[u]+len[j],Q.push(to[j]),a[++cur]=dis[to[j]];
    			}
    			for(int k=1;k<=q;k++)if(!ans[k])for(int j=1;j<=cur;j++)if(S.find(qq[k]-a[j])!=S.end())ans[k]=1;
    			for(int j=1;j<=cur;j++)S.insert(a[j]);
    		}
    }
    
    inline void solve(int u)
    {
    	for(int i=fir[rt];i;i=nxt[i])
    		if(!vis[to[i]])
    		{
    			N=sz[to[i]];
    			getrt(to[i],to[i]);
    			dfs(rt,rt),cal(rt),vis[rt]=1;
    			solve(to[i]);
    		}
    }
    
    int main()
    {
    	n=getint(),q=getint();
    	for(int i=1;i<n;i++)
    	{
    		int u=getint(),v=getint(),w=getint();
    		newnode(u,v,w),newnode(v,u,w);
    	}
    	for(int i=1;i<=q;i++)qq[i]=getint();
    	N=n;getrt(1,1);
    	dfs(rt,rt),cal(rt);vis[rt]=1;
    	solve(rt);
    	for(int i=1;i<=q;i++)
    		if(!qq[i]||ans[i])printf("Yes
    ");
    		else printf("No
    ");
    }
    

  • 相关阅读:
    Java读写锁(ReentrantReadWriteLock)学习
    水平拆分和垂直拆分理解(未完)
    MySQL 主从复制
    sharding-JDBC 实现读写分离
    Linux查看程序端口占用情况
    sharding-jdbc 实现分表
    MySQL explain
    MySQL的七种join
    MySQL建立高性能索引策略
    Nginx企业级优化
  • 原文地址:https://www.cnblogs.com/Darknesses/p/12243495.html
Copyright © 2011-2022 走看看