数苹果

Description
【背景】

Hcs的数学越来越堪忧,甚至连数(shu3)数(shu4)都不能保证正确率了。

为了考察Hcs能不能数对自然数,老师决定带他去菜市场数苹果做为考试。

【问题描述】

菜市场有一排n个苹果筐,编号为1到n,每个苹果框最多只能装k个苹果,也可以是空的。老师要求Hcs说m句话来考察他的数学。最后考试成绩为正确的陈述的数量除以m。

每句话包含三个数 ci,ai,bi.表示从第ai个框到第bi个框一共的苹果数量除以(k+1)的余数为ci(保证0<=ci<=k).

一句话是正确的,当且仅当之前所有正确的话都不会与这句话产生冲突。

根据题意,第一句话总是对的。

Input
第一行包含三个数:正整数n , 正整数m, 正整数k;

接下来m行,第1+i行包含三个数:

非负整数ci,正整数ai,正整数bi.

Output
只有一行:输出Hcs最终成绩,小数点后保留5位小数。

Sample Input
5 4 1
0 3 3
1 4 4
0 3 4
1 1 4
Sample Output
0.75000
HINT
对与20%的数据:k=1 , n<=1000, m<=1000;

对于50%的数据:k<=20,n<=100000,m<=100000;

对于100%的数据:0<ai<=bi<=n<=100000,0<k1000,0<m500000;


并査集.
跟之前发过的那一道<食物链>几乎是一样的, 就是换了个壳子.
http://blog.csdn.net/kenxhe/article/details/52938486
对于一个区间[a, b], 维护其在并査集上到祖先节点的权值和s[a - 1], s[b]即可.考虑递推式的时候, 可先忽略%操作, 这样更容易想一些.
注意取模时的正负性(很简单的处理一下).
总而言之, 此题只需要将<食物链>上的% 3改为% (k + 1)即可.
贴代码.

#include<iostream>
using namespace std;
const int maxN = (int)1e5;
int pre[maxN + 1], sum[maxN + 1];
int k;
void getRoot(int u)
{
    if(pre[u] == u)
        return;
    getRoot(pre[u]);
    sum[u] = (sum[u] + sum[pre[u]] + k) % k;
    pre[u] = pre[pre[u]];
} 
int main()
{
    int n, m;
    ios::sync_with_stdio(false);
    cin >> n >> m >> k;
    k ++;
    int ans = m;
    for(int i = 0; i <= n; i ++)
        pre[i] = i, sum[i] = 0;
    for(int i = 0; i < m; i ++)
    {
        int a, b, c;
        cin >> c >> a >> b;
        a --;
        getRoot(a);
        getRoot(b);
        if(pre[a] != pre[b])
            sum[pre[b]] = (c - sum[b] + sum[a] + k) % k, pre[pre[b]] = pre[a];
        else if (pre[a] == pre[b] && (sum[b] - sum[a] + k) % k != c)
            ans --;
    }
    printf("%.5f", (double)ans / (double)m);
 }

这么水的题居然都没有打出来…药丸!!

原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6402873.html