解法
C++的整数长度真是令人头秃
解法本身不难,假如我们有个大小为
1
0
9
10^9
109的数组,Line Sweep遍历每个下标的时候可以得到该下标的点的个数
但是数组太大了,只能采取离散化的思想,用map
记录坐标轴
每个R
+1,表示多一个新区间,每个L-1
-1,表示离开一个区间
最后从后往前遍历map
,遍历到i
的时候累加的前缀和grp
(还没加上map[i]
时的值)表示的是(i,i->next]
之间有多少组并行,即在这个区间内,每个都会出现grp
次
如果要求这个区间里第k
个(从0开始),那么它的数字应该对应的是i->next-k/grp
。
#include <stdio.h>
#include <string>
#include <iostream>
#include <memory.h>
#include <stdlib.h>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
#define MAXN 400010
#define MAXQ 100010
#define ZERO 10e-6
using namespace std;
typedef long long lld;
int n,q;
int X[MAXN],Y[MAXN],Z[MAXQ];
int L[MAXN],R[MAXN];
pair<int,int> K[MAXQ];
lld A[3],B[3],C[3],M[3];
map<int,int> axis;
int main() {
// freopen("/Users/huangyuemei/CLionProjects/untitled/B-small-practice.in","r",stdin);
// freopen("/Users/huangyuemei/CLionProjects/untitled/my.out","w",stdout);
int t;
scanf("%d",&t);
for(auto round=1;round<=t;++round) {
scanf("%d%d",&n,&q);
scanf("%d%d%d%d%d%d",&X[0],&X[1],&A[0],&B[0],&C[0],&M[0]);
scanf("%d%d%d%d%d%d",&Y[0],&Y[1],&A[1],&B[1],&C[1],&M[1]);
scanf("%d%d%d%d%d%d",&Z[0],&Z[1],&A[2],&B[2],&C[2],&M[2]);
for(int i=2;i<n;i++) {
X[i] = ((lld)A[0]*X[i-1]+(lld)B[0]*X[i-2]+C[0])%M[0];
Y[i] = ((lld)A[1]*Y[i-1]+(lld)B[1]*Y[i-2]+C[1])%M[1];
}
for(int i=2;i<q;++i) {
Z[i] = ((lld)A[2]*Z[i-1]+(lld)B[2]*Z[i-2]+C[2])%M[2];
}
axis.clear();
// int all = 0;
for(int i=0;i<n;++i) {
L[i] = min(X[i],Y[i]);
R[i] = max(X[i],Y[i])+1;
axis[L[i]] -= 1;
axis[R[i]] += 1;
// all += R[i]-L[i];
}
for(int i=0;i<q;++i) {
K[i].first = Z[i];
K[i].second = i+1;
}
sort(K,K+q);
int ptr = 0, grps = 0, prev = 0;
lld total = 0;
lld ans = 0;
for(auto it = axis.end();it!=axis.begin();) {
it--;
lld interL = (lld)(prev-it->first)*grps;
while(ptr<q && K[ptr].first-total<interL) {
ans += (lld)(prev-(K[ptr].first-total)/grps)*K[ptr].second;
ptr++;
}
if(ptr==q) break;
prev = it->first;
grps += it->second;
total += interL;
}
// printf("%lld\n",all);
printf("Case #%d: %lld\n",round,ans);
}
}