zoukankan      html  css  js  c++  java
  • BSOJ3392【省选模拟】树上的询问

    题目

    BSOJ3392【省选模拟】树上的询问

    分析

    点分治。

    点分治入门题,首先这题可以直接做,也可以转化成 "小于等于 (k) 的减掉 小于等于 (k-1) 的" ,然后相减来做。

    两者皆可。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    inline int inc(int x,int v,int mod){x+=v;return x>=mod?x-mod:x;}
    inline int dec(int x,int v,int mod){x-=v;return x<0?x+mod:x;}
    inline int read(){int x=0,f=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
    inline void write(int x){if(x==0){putchar(48);return;}int len=0,dg[20];while(x>0){dg[++len]=x%10;x/=10;}for(register int i=len;i>=1;i--)putchar(dg[i]+48);}
    const int N=1e5+5;
    const int M=1e7+5;
    struct node{
        int to,next,val;
    }edge[1000005];
    int used[N],head[N],idy,q[N],maxson[N],tot,size[N],dis[N],rev[N],cnt;
    bool vis[N],ans[N],rvis[M];
    int n,m,id,idx;
    void add(int u,int v,int w){
        edge[++idx].to=v;
        edge[idx].next=head[u];
        edge[idx].val=w;
        head[u]=idx;
        return ;
    }
    void dfs(int x,int fa){ 
    	size[x]=1;
    	maxson[x]=0;
    	for(int i=head[x];i;i=edge[i].next){
    		int y=edge[i].to;
    		if(y==fa||vis[y])continue;
    		dfs(y,x);
    		size[x]+=size[y];
    		maxson[x]=max(maxson[x],size[y]);
    	}
    	maxson[x]=max(maxson[x],tot-size[x]);
    	if(maxson[x]<maxson[id])id=x;
    	return ;
    }
    void dist(int x,int fa){
    	rev[++cnt]=dis[x];
    	for(int i=head[x];i;i=edge[i].next){
    		int y=edge[i].to;
    		if(y==fa||vis[y])continue;
    		dis[y]=dis[x]+edge[i].val;
    		dist(y,x);
    	}
    }
    void calc(int x){
    	idy=0;
    	for(int i=head[x];i;i=edge[i].next){
    		int y=edge[i].to;
    		if(vis[y])continue;
    		cnt=0;
    		dis[y]=edge[i].val;
    		dist(y,x);
    		for(int j=1;j<=cnt;j++){
    			for(int k=1;k<=m;k++){
    				if(q[k]-rev[j]>=0&&q[k]-rev[j]<=1e7 && rvis[q[k]-rev[j]])ans[k]=1;
    			}
    		}
    		for(int j=1;j<=cnt;j++) if(rev[j]<=1e7)used[++idy]=rev[j],rvis[rev[j]]=1;
    	}
    	for(int i=1;i<=idy;i++)rvis[used[i]]=0;
    }
    void solve(int x){
    	vis[x]=rvis[0]=1;
    	calc(x);
    	for(int i=head[x];i;i=edge[i].next){
    	    int y=edge[i].to;
    		if(vis[y])continue;
    		id=0;
    		maxson[id]=tot=size[y];
    		dfs(y,0);
    		solve(id);
    	}
    }
    int main(){
        n=read(),m=read();
        for(int i=1;i<=n-1;i++){
            int x=read(),y=read(),z=read();
            add(x,y,z),add(y,x,z);
        }
    	for(int i=1;i<=m;i++)q[i]=read();
        maxson[id]=tot=n;
        dfs(1,0);
        solve(id);
        for(int i=1;i<=m;i++){
        	printf("%s
    ",(ans[i]||(!q[i])) ? "Yes" : "No");
    	}
    	return 0;
    }
    

    感受

    这题第二种做法很巧妙,同样的办法在一道模拟题也见过,同样是容斥,但是那道题是 (dp)

  • 相关阅读:
    VBS进程判断
    [转]Myeclipse的使用方法格式化源代码
    Stay hungry,stay foolish
    【转】tomcat 设置 session 过期时间
    【转】Java编码转换问题,new String(str.getByts("ISO88591"), "GBK")的作用
    【转】VBS CHR码值对应列表
    【转】 从MS SQL Server 2000升级到MS SQL Server 2005方法
    【转】SqlServer中decimal(numeric )、float 和 real 数据类型的区别
    html radio
    a标签点击状态
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14738567.html
Copyright © 2011-2022 走看看