题目链接
题面
题目描述
奶牛们正在努力尝试发明有趣的新游戏来玩。他们目前的工作之一与一组 N N N 个区间( 1 ≤ N ≤ 2 ⋅ 1 0 5 1≤N≤2⋅10^5 1≤N≤2⋅105)有关,其中第 i i i 个区间从数轴上的 a i a_i ai 位置开始,并在位置 b i ≥ a i b_i≥a_i bi≥ai 结束。 a i a_i ai 和 b i b_i bi 均为 0 … M 0…M 0…M 范围内的整数,其中 1 ≤ M ≤ 5000 1≤M≤5000 1≤M≤5000。
这个游戏的玩法是,Bessie 选择某个区间(假设是第 i i i 个区间),而她的表妹 Elsie 选择某个区间(假设是第 j j j 个区间,可能与 Bessie 所选的的区间相同)。给定某个值 k k k,如果 a i + a j ≤ k ≤ b i + b j a_i+a_j≤k≤b_i+b_j ai+aj≤k≤bi+bj,则她们获胜。
对范围 0 … 2 M 0…2M 0…2M 内的每个值 k k k,请计算使得 Bessie 和 Elsie 可以赢得游戏的有序对 ( i , j ) (i,j) (i,j) 的数量。
输入
输入的第一行包含 N N N 和 M M M。
以下 N N N 行每行以整数 a i a_i ai 和 b i b_i bi 的形式描述一个区间。
输出
输出 2 M + 1 2M+1 2M+1 行,依次包含范围 0 … 2 M 0…2M 0…2M 中的每一个 k k k 的答案。
样例输入
2 5
1 3
2 5
样例输出
0
0
1
3
4
4
4
3
3
1
1
提示
【样例解释】
在这个例子中,对于 k = 3 k=3 k=3,有三个有序对可以使得 Bessie 和 Elsie 获胜: ( 1 , 1 ) , ( 1 , 2 ) (1,1),(1,2) (1,1),(1,2),和 ( 2 , 1 ) (2,1) (2,1)。
【数据范围】
测试点 1-2 满足 N ≤ 100 , M ≤ 100 N≤100,M≤100 N≤100,M≤100。
测试点 3-5 满足 N ≤ 5000 N≤5000 N≤5000。
测试点 6-20 没有额外限制。
注意输出可能无法用 32 位整数型存储,你可能需要使用 64 位整数型(例如,C 或 C++ 中的 “long long”)。
暴力思路(10pts)
我们发现,我们只需要模拟画出一个图然后进行暴力枚举就行了。
差分+桶+加乘原理思路(100pts)
我们明显发现,这道题是可以运用差分的思想去做的,即 a i + a j a_i+a_j ai+aj 的地方加上 x i × x j x_i \times x_j xi×xj , b i + b j + 1 b_i+b_j+1 bi+bj+1 的地方减去 y i × y j y_i \times y_j yi×yj 。
但是我们发现这样子做时间复杂度是 O ( n 2 ) O(n^2) O(n2) ,我们发现 a , b , m a,b,m a,b,m 的值域很小,可以考虑用桶存起来,时间复杂度 O ( m 2 ) O(m^2) O(m2)
AC CODE
#include<iostream>
#include<cstdio>
long long a[100005],b[100005],cnt[100005],ans;
using namespace std;
int main(){
int n,m,x,y;
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%d %d",&x,&y);
a[x]++;
b[y]++;
}
for(int i=0;i<=m;i++){
for(int j=0;j<=m;j++){
cnt[i+j]+=a[i]*a[j],cnt[i+j+1]-=b[i]*b[j];
}
}
m*=2;
for(int i=0;i<=m;i++){
ans+=cnt[i];
printf("%lld\n",ans);
}
return 0;
}