1 条题解
-
3
20pts
暴力。
60pts
首先我们发现对于任意一个插班生的座位,听课认真度减少量为和,这部分贡献可以直接算出来。
100pts
但是我们发现对于,会直接减到贡献不足,我们考虑预处理出不足的贡献。 对于一位同学,当插班生在时,他会有的不足的贡献,观察不难得出,当插班生在时,同学不足的贡献分别为,同理,当插班生在时,不足的贡献分别为,是一个等差数列,于是考虑二阶差分。 对于差分数组,我们处理一个的数列,观察不难得出差分数组为,于是得到二维差分数组为,即,,。我们对于每一个统计同一个数组,最后不忘减去自身被插班生占去的贡献单独讨论,最后两次前缀和合并数组。注意到左右端点容易有问题,我这里直接处理的,数组就爆了。 最后合并即
#include<bits/stdc++.h> #define int long long//小心见祖宗 using namespace std; int n; int a[600005]; int d[600020]; void work(int x,int val) { d[x - (val - 1) + 200001] += 1,d[x + 1 + 200001] += -2,d[x + val + 1 + 200001] += 1; } signed main() { cin >> n ; int sum = 0; for(int i =1;i <= n;i++) { cin >> a[i]; sum += a[i]; } // work(2,5); for(int i = 1;i <= n;i++) if(a[i] < n) work(i,n - a[i]); for(int i = 1;i <= 400003;i++) d[i] += d[i - 1]; for(int i = 1;i <= 400003;i++) d[i] += d[i - 1]; for(int i = 1;i <= n;i++) if(a[i] < n) d[i + 200001] -= n - a[i]; for(int i = 1;i <= n;i++) { int sum1 = (i + n - 1) * (n - i) / 2,sum2 = (2 * n - i) * (i - 1) / 2; cout << sum - sum1 - sum2 + d[i + 200001] - a[i] << ' ' ; } return 0; }
- 1
信息
- ID
- 12
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- (无)
- 递交数
- 89
- 已通过
- 14
- 上传者