考试题目——雪后村庄

题目描述
这里写图片描述

输入
这里写图片描述

输出
输出q行,每行一个字符串“yes”或“no”(不包括引号)。

样例输入
Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

2 4
3 4
1 2 3
2 3 2
2 4 4
1 2 3
1 3 2
2 3 2
3 4 4
4
1 3 3
1 3 2
1 4 3
3 4 4
样例输出
no
yes
no
no
提示
这里写图片描述

如果按着他的输入来做的话,你就炸了

由于每个车夫(lao si ji)的能力(fan che)值,只与某些路径中最小的那一段比较,还不需要保存,倍增和LCA来做铁定超时

这么多解决树上问题的姿势,为什么非要用这一种呢,并查集不也是解决这个问题很好的做法吗,将所有的边按边长从大到小排序,并将车夫(lao si ji)的能力(fan che)值从大到小排序,当某一次要处理的边小于了目前访问到的车夫(lao si ji)的能力(fan che)值,就先将这个车夫(lao si ji)的问题解决

时间复杂度:O(qn),瞬间爆炸

这个n能不能优化掉呢?
yy到了哈希

将某一户人家,它在每个村子里的并查集编号,用哈希从一位数组压缩到一个整数

例:第i户人家,它在第j个村庄的并查集编号为x
hash[i]+=xmaxnj

由于maxnj太大,可将它模一个质数,如998244353

但有时候模下来会有重复,则使用双哈希,同一个哈希模另一个质数,如1e9+7

双哈希在NOIP中几乎无敌,不会有丧心病狂的卡双哈希的数据的

头一次写双哈希,WA了十几次,QwQ
AC代码如下:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

#define mod1 998244353
#define mod2 1000000007
#define maxn 200000
#define maxr 300000

using namespace std;

inline long long getint()
{
    long long 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;
}

struct node{
    long long u,v,w,bl;
}road[maxr+5],dri[maxn+5];

inline bool cmp(node x,node y){return x.w>y.w;}

long long n,m,q,rd[maxn+5];
long long hash1[maxn+5],hash2[maxn+5],ksm1[maxn+5],ksm2[maxn+5];
long long fir[maxn+5],nxt[2*maxr+5],to[2*maxr+5],cnt;
long long f[maxn+5],sum[maxn+5],siz[maxn+5];
bool ans[maxn+5];

inline void dfs(long long x,long long ch,long long ne)
{
    for(long long i=fir[x];i;i=nxt[i])
        if(f[to[i]]==ne)
        {
            hash1[(to[i]-1)%m+1]=((hash1[(to[i]-1)%m+1]-(ne*ksm1[(to[i]-1)/m+1])%mod1)%mod1+mod1)%mod1;
            hash1[(to[i]-1)%m+1]=(hash1[(to[i]-1)%m+1]+(ch*ksm1[(to[i]-1)/m+1])%mod1)%mod1;
            hash2[(to[i]-1)%m+1]=((hash2[(to[i]-1)%m+1]-(ne*ksm2[(to[i]-1)/m+1])%mod2)%mod2+mod2)%mod2;
            hash2[(to[i]-1)%m+1]=(hash2[(to[i]-1)%m+1]+(ch*ksm2[(to[i]-1)/m+1])%mod2)%mod2;
            f[to[i]]=ch,siz[ch]++,siz[ne]--;
            dfs(to[i],ch,ne);
        }
}

inline void work(long long i)
{
    long long u=road[i].u,v=road[i].v;
    if(siz[f[u]]>=siz[f[v]])
    {
        hash1[(v-1)%m+1]=((hash1[(v-1)%m+1]-(f[v]*ksm1[(v-1)/m+1])%mod1)%mod1+mod1)%mod1;
        hash1[(v-1)%m+1]=(hash1[(v-1)%m+1]+(f[u]*ksm1[(v-1)/m+1])%mod1)%mod1;
        hash2[(v-1)%m+1]=((hash2[(v-1)%m+1]-(f[v]*ksm2[(v-1)/m+1])%mod2)%mod2+mod2)%mod2;
        hash2[(v-1)%m+1]=(hash2[(v-1)%m+1]+(f[u]*ksm2[(v-1)/m+1])%mod2)%mod2;
        long long hh=f[v];f[v]=f[u];dfs(v,f[u],hh);
        siz[hh]--,siz[f[u]]++;
    }
    else
    {
        hash1[(u-1)%m+1]=((hash1[(u-1)%m+1]-(f[u]*ksm1[(u-1)/m+1])%mod1)%mod1+mod1)%mod1;
        hash1[(u-1)%m+1]=(hash1[(u-1)%m+1]+(f[v]*ksm1[(u-1)/m+1])%mod1)%mod1;
        hash2[(u-1)%m+1]=((hash2[(u-1)%m+1]-(f[u]*ksm2[(u-1)/m+1])%mod2)%mod2+mod2)%mod2;
        hash2[(u-1)%m+1]=(hash2[(u-1)%m+1]+(f[v]*ksm2[(u-1)/m+1])%mod2)%mod2;
        long long hh=f[u];f[u]=f[v];dfs(u,f[v],hh);
        siz[hh]--,siz[f[v]]++;
    }
}

inline void newnote(long long u,long long v){to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}

inline void init()
{
    ksm1[1]=ksm2[1]=1;
    for(long long i=2;i<=maxn;i++)
    {
        ksm1[i]=(ksm1[i-1]*(maxn+1)%mod1);
        ksm2[i]=(ksm2[i-1]*(maxn+1)%mod2);
    }
}

int main()
{
    init();
    long long i,j;
    n=getint(),m=getint();
    for(i=1;i<=n;i++)sum[i]=(rd[i]=getint())+sum[i-1];
    for(i=1;i<=n;i++)
        for(j=1;j<=rd[i];j++)
        {
            road[sum[i-1]+j].u=getint()+m*(i-1);
            road[sum[i-1]+j].v=getint()+m*(i-1);
            road[sum[i-1]+j].w=getint(),road[sum[i-1]+j].bl=i;
            newnote(road[sum[i-1]+j].u,road[sum[i-1]+j].v);
            newnote(road[sum[i-1]+j].v,road[sum[i-1]+j].u);
        }
    for(i=1;i<=n*m;i++)
    {
        f[i]=i,siz[i]=1;
        hash1[(i-1)%m+1]=(hash1[(i-1)%m+1]+(i*ksm1[(i-1)/m+1]%mod1))%mod1;
        hash2[(i-1)%m+1]=(hash2[(i-1)%m+1]+(i*ksm2[(i-1)/m+1]%mod2))%mod2;
    }
    sort(road+1,road+sum[n]+1,cmp);
    q=getint();
    for(i=1;i<=q;i++)
        dri[i].u=getint(),dri[i].v=getint(),dri[i].w=getint(),dri[i].bl=i;
    sort(dri+1,dri+q+1,cmp);
    long long tmp=1;
    for(i=1;i<=sum[n];i++)
    {
        while(road[i].w<dri[tmp].w&&tmp<=q)
        {
            if(hash1[dri[tmp].u]==hash1[dri[tmp].v]&&hash2[dri[tmp].u]==hash2[dri[tmp].v])
                ans[dri[tmp].bl]=1;
            tmp++;
        }
        if(f[road[i].u]!=f[road[i].v])work(i);
    }
    while(tmp<=q)
    {
        if(hash1[dri[tmp].u]==hash1[dri[tmp].v]&&hash2[dri[tmp].u]==hash2[dri[tmp].v])
            ans[dri[tmp].bl]=1;
        tmp++;
    }
    for(i=1;i<=q;i++)
        if(ans[i])printf("yes\n");
        else printf("no\n");
}
posted @ 2017-08-19 17:25  Izayoi_Doyo  阅读(137)  评论(0编辑  收藏  举报