数苹果
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
并査集.
跟之前发过的那一道<食物链>几乎是一样的, 就是换了个壳子.
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);
}
这么水的题居然都没有打出来…药丸!!