zoukankan      html  css  js  c++  java
  • USACO 2019DEC Milk Visits

    题目链接

    题意简述

    求树上路径((u,v))上是否存在(H/G)

    题目解析

    一个比较明显的做法是用树上前缀和,用(H[i]/G[i])表示从根到(i)(H/G)的个数,处理询问的时候,(ans=H/G[u]+H/G[v]-H/G[lca]-H/G[f[lca]])(lca)自己不能减去),类似于求(dis)的做法。

    但是重点不是这个,我在题解区看到了一个更简单的做法,记录一下。

    我们把颜色相同的,在树上有边相连的点连成一个连通块,用并查集维护。

    那么同一个联通块里可以相互到达,并且不会经过另外一种牛奶。

    所以如果查询的(u,v)在同一个连通块里,并且和连通块的牛奶不一样,那么就不高兴,否则会高兴。


    ►Code View Ver.1

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    #define LL long long
    #define N 100005
    #define DEL 100000
    #define INF 0x3f3f3f3f
    int rd()
    {
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48); c=getchar();}
    	return f*x;
    }
    int n,m,d;
    char s[N];
    vector<int>G[N];
    int dep[N],f[N][20],h[N],g[N];
    void dfs(int u,int fa)
    {
    	dep[u]=dep[fa]+1;
    	f[u][0]=fa;
    	if(s[u]=='H') h[u]=1;
    	else g[u]=1;
    	h[u]+=h[fa],g[u]+=g[fa];
    	for(int i=1;i<=d;i++)
    		f[u][i]=f[f[u][i-1]][i-1];
    	for(int i=0;i<G[u].size();i++)
    	{
    		int v=G[u][i];
    		if(v==fa) continue;
    		dfs(v,u);
    	}
    }
    int LCA(int u,int v)
    {
    	int tmp;
    	if(dep[u]<dep[v]) tmp=u,u=v,v=tmp;
    	for(int i=d;i>=0;i--)
    		if(dep[f[u][i]]>=dep[v]) u=f[u][i];
    	if(u==v) return u;
    	for(int i=d;i>=0;i--)
    		if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
    	return f[u][0];
    }
    int main()
    {
    	n=rd(),m=rd();
    	d=1;
    	while((1<<d)<n) d++;
    	scanf("%s",s+1);
    	for(int i=1;i<=n-1;i++)
    	{
    		int u=rd(),v=rd();
    		G[u].push_back(v);
    		G[v].push_back(u);
    	}
    	dfs(1,0);
    	char pfer[5];
    	while(m--)
    	{
    		int u=rd(),v=rd();
    		scanf("%s",pfer);
    		int lca=LCA(u,v),val;
    		if(pfer[0]=='H') val=h[u]+h[v]-h[lca]-h[f[lca][0]];
    		else val=g[u]+g[v]-g[lca]-g[f[lca][0]];
    		if(val) printf("1");
    		else printf("0");
    	}
    	return 0;
    } 
    
    

    ►Code View Ver.2

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    #define LL long long
    #define N 100005
    #define DEL 100000
    #define INF 0x3f3f3f3f
    int rd()
    {
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48); c=getchar();}
    	return f*x;
    }
    int n,m;
    char s[N];
    vector<int>G[N];
    int f[N];
    int Find(int x)
    {
    	if(f[x]==x) return x;
    	return f[x]=Find(f[x]);
    }
    void Union(int u,int v)
    {
    	u=Find(u),v=Find(v);
    	if(u<v) f[u]=v;
    	else f[v]=u;
    }
    void Init()
    {
    	for(int i=1;i<=n;i++)
    		f[i]=i;
    }
    int main()
    {
    	n=rd(),m=rd();
    	scanf("%s",s+1);
    	Init();
    	for(int i=1;i<=n-1;i++)
    	{
    		int u=rd(),v=rd();
    		if(s[u]==s[v]) Union(u,v);
    	}
    	while(m--)
    	{
    		int u=rd(),v=rd();
    		char pfer[5];
    		scanf("%s",pfer);
    		u=Find(u),v=Find(v);
    		if(u==v&&s[u]!=pfer[0]) printf("0");
    		else printf("1");
    	}
    	return 0;
    } 
    
  • 相关阅读:
    Graylog安装操作
    CF1012C Hills
    MySQL 加锁处理分析
    2.22考试
    int(1)和int(11)是否有区别?
    「LibreOJ NOI Round #1」验题
    MySQL一致性非锁定读
    [学习笔记]凸优化/WQS二分/带权二分
    MySQL latch小结
    [八省联考2018]林克卡特树lct——WQS二分
  • 原文地址:https://www.cnblogs.com/lyttt/p/13992740.html
Copyright © 2011-2022 走看看