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)

  • 相关阅读:
    CSS3 target伪类简介
    不用position,让div垂直居中
    css3 在线编辑工具 连兼容都写好了
    a标签伪类的顺序
    oncopy和onpaste
    【leetcode】1523. Count Odd Numbers in an Interval Range
    【leetcode】1518. Water Bottles
    【leetcode】1514. Path with Maximum Probability
    【leetcode】1513. Number of Substrings With Only 1s
    【leetcode】1512. Number of Good Pairs
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14738567.html
Copyright © 2011-2022 走看看