题目描述
水宝宝某天突发奇想,在纸上写了这样一个问题:
给一个a数组,求∑∞i=1get(l,r,i)⋅∑∞i=1get(l1,r1,i)
,其中get(l,r,x)表示求a[l]~a[r]中x出现了几次,他很快推出了规律,
但正当他把这道题录入电脑是发现作为一个蒟蒻的他不会打latex也没找到数学符号(主要是懒),
所以他省略了那个∑
式子,于是,题面变为了求get(l,r,x)*get(l1,r1,x)的值了. 为了防数据过大,你要对20180623取模
不保证l<r,l1<r1,遇到这种情况,请先交换一下
输入描述:
第一行一个n,m 接下来一行n个数表示a[i] 接下来m行,每行l,r,l1,r1,x,表示求get(l,r,x)*get(l1,r1,x)
输出描述:
3×m行,先输出get(l,r,x),再输出get(l1,r1,x),再输出get(l,r,x)*get(l1,r1,x)
示例1
输入
5 1 2 2 2 2 2 1 5 1 3 2
输出
5 3 15
说明
对于所有数据1<=n,m<=105;1<=l,r,l1,r1<=105
;a[i]≤10000,x≤100000
提示:20180623不是质数
这题区间排序+二分可以做模板。
首先我们创建vector数组,vector[i]存依次i的出现位置,由于依次输入,那么vector内必定有序,利用lower_bound和upper_bound计算区间内x的个数即可。
#include"iostream"
#include"cstdio"
#include"vector"
#include"algorithm"
#define mod 20180623
using namespace std;
typedef long long ll;
void swap(int &a,int &b){
ll t = a+b;
b = max(a,b);
a = t - b;
}
vector <int> V[100000+5];
int main(){
int N,M,a;
scanf("%d%d",&N,&M);
for(int i = 1;i <= N;i++){
scanf("%d",&a);
V[a].push_back(i);
}
for(int i = 0;i < M;i++){
int l,r,l1,r1,tag;
scanf("%d",&l);
scanf("%d",&r);
scanf("%d",&l1);
scanf("%d",&r1);
scanf("%d",&tag);
swap(l,r);
swap(l1,r1);
int sum1 = upper_bound(V[tag].begin(),V[tag].end(),r) - lower_bound(V[tag].begin(),V[tag].end(),l);
int sum2 = upper_bound(V[tag].begin(),V[tag].end(),r1) - lower_bound(V[tag].begin(),V[tag].end(),l1);
printf("%d\n",sum1%mod);
printf("%d\n",sum2%mod);
printf("%d\n",((sum1%mod)*(sum2%mod))%mod);
}
return 0;
}