【并查集】凌辱

来源:互联网 发布:三国杀 郭淮 知乎 编辑:程序博客网 时间:2024/05/17 22:16
凌辱凌辱 


 【问题描述】 
     13 级的男生太菜了,于是神母牛小希准备在省选的前一天晚上在宾馆凌辱他们,男生 
们由于众不敌寡只有乖乖听话。 
    宾馆有n 个房间,她把男生们随机安排进宾馆的一些房间。由于小希记忆力有限,她仅 
仅记得从第a 号到第b 号房间一共关了多少个男生。现在小希把她知道的所有信息都告诉你, 
然后询问你从第c 号到第d 号房间一共关了多少男生,如果无法得出确切答案,请回答“hehe ” 
来卖萌(引号无需输出)。 
    记住,凌辱与被凌辱,小希就在那里。 


 【输入数据】 
第一行三个整数n,m,k,表示共有n 个房间,m 条信息和k 次询问。 
接下来m 行每行3 个整数a b c,表示区间[a,b]的房间关了c 个男生。 
接下来k    行每行2 个整数a b,表示询问区间[a,b]的房间关了多少个男生。 


 【输出数据】 
共k 行,每行表示一次询问的结果。 


 【样例输入】                              【样例输出】 
10 4 3                               2 
1 3 5                                3 
2 3 3                                hehe 
5 8 6 
6 7 3 
1 1 
6 7 
2 4 


 【样例解释】 
红色区域代表小希的信息,绿色区域表示通过计算能算出的区域。 


 【数据范围及约定】 
1≤n≤3000,0≤m≤10000,0≤k≤10000。 
输入数据保证正确性,无需验证。 

答案和中间值都在longint 范围内。 



看着很像是线段树,实际上是考察并查集,每加一条边就把首位两个点所在的集合合并,查询的时候,必须要满足左右端点在同一个集合中才能有解,否则就"hehe"。

维护每一个点到他的父亲的距离,在find中必须要更新,而且很容易打错


    long r = f[a];
    f[a] = find(f[a]);
    d[a] += d[r];
    return f[a];

必须首先要find(f[a]),才能d[a]+=d[r],因为首先要更新父亲的父亲,再修改父亲现在到新的父亲的距离。

两点之间的距离即两点到根节点的距离之差。即人的数量



#include <cstdio>long f[3002];long d[3002];long find(long a){    if (f[a] == a)        return a;//    long r = find(f[a]);//    d[a] += d[r];//    return r;//    long r = f[a];//    d[a] += d[r];//    return f[a] = find(f[a]);    long r = f[a];    f[a] = find(f[a]);    d[a] += d[r];    return f[a];}int main(){    freopen("insult.out","w",stdout);    freopen("insult.in","r",stdin);    long n;long m;long k;    scanf("%ld%ld%ld",&n,&m,&k);    for (long i=1;i<n+1;i++)    {        f[i] = i;    }    for (long i=1;i<m+1;i++)    {        long a;long b;long c;        scanf("%ld%ld%ld",&a,&b,&c);        long aa = find(a-1);        long bb = find(b);        if (aa!=bb)        {            f[aa] = bb;            d[aa] = c-d[a-1]+d[b];        }    }    for (long i=1;i<k+1;i++)    {        long a;long b;        scanf("%ld%ld",&a,&b);        long aa = find(a-1);        long bb = find(b);        if (aa!=bb)        {            printf("hehe\n");        }        else        {            printf("%ld\n",d[a-1]-d[b]);        }    }    return 0;}


原创粉丝点击