题意:每个班级的分数是[L_i,R_i],区间内的分数有且只有一个。一共N个班级,有Q个query,问第K高的分数是多少。
有点类似于区间合并问题。先将区间转成左闭右开的[l,r),从小到大排序后扫描区间,遇到左端点+1,遇到右端点-1,扫描之后就得知每个点被几个区间覆盖了。
然后再求后缀和,对于每个点x,suffixsum[x]表示分数>=x的个数。通过二分搜索lower_bound可以找出第一个<=K的分数x。如果x对应的个数恰好等于K,则x就是对应的第K大的分数。否则,target 分数在[x0,x]之间,其中x0是排序后x左侧的分数,可以根据覆盖[x0,x]的区间个数求出对应的分数。例如,有三个区间覆盖[1,4),那么区间内的分数是[1,1,1,2,2,2,3,3,3],算个倍数下取整就可以得出对应哪一个分数。
因为suffixsum是降序,所以要重载lower_bound函数。suffixsum每个元素是一个pair (x,y) (score: x, number of scores that >=x: y),lower_bound返回的是第一个>= target的个数,而我们需要找的是第一个<=y的个数,所以应该让y大的往前排。
如果target的y是3,现有的数组是6,4,2,1,按照这个规矩,3应该插在4和2之间,所以返回2.
另外,对于y相等的情形,应该找到最后右边的x。某个x如果是右边开区间的端点,可能分数=x的student不存在。例如[1,3) and [5,7) ,K=2时应该返回5而不是3.这种情况下,可以target pair设成(-1,target),分数x大的往前排,就可以保证y相同时找到最右边的x。例如 target is (-1,3),suffix array是(1,4),(2,3),(3,3),(4,1),target应该插在(3,3)右边,返回(4,1)。
最后又被overflow卡了许久。。本来以为这个数量级不会超出int的。。
#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
//Kickstart Round G Problem B. Combining Classes
const int maxn=800010;
int T;
int N;
int Q;
long long X[maxn];
long long Y[maxn];
long long Z[maxn];
long long A[3];
long long B[3];
long long C[3];
long long M[3];
long long L[maxn];
long long R[maxn];
long long K[maxn];
long long ans;
vector<pair<long long,long long> >arr;
pair<long long,long long> presum[maxn];
pair<long long,long long> suffixsum[maxn];//f(x), how many people with score >=x
map<long long,long long>mp;//map index to count
bool cmp(pair<long long,long long>a, pair<long long,long long>b)
{
if(a.first==b.first)
{
return a.second>b.second;
}
return a.first<b.first;
}
bool searchcmp(pair<long long,long long>a, pair<long long,long long>b)
{
if(a.second==b.second)
{
return a.first>b.first;//to deal with the case with multiple same second, e.g., [1,3),[5,7)
}
return a.second>b.second;
}
int main()
{
freopen("input.txt","r",stdin);
// freopen("B-large-practice.in","r",stdin);
// freopen("B.txt","w",stdout);
clock_t START_TIME;
clock_t FINISH_TIME;
START_TIME=clock();
scanf("%d",&T);
for(int ca=1;ca<=T;ca++)
{
memset(A,0,sizeof(A));
memset(B,0,sizeof(B));
memset(C,0,sizeof(C));
memset(M,0,sizeof(M));
memset(L,0,sizeof(L));
memset(R,0,sizeof(R));
memset(K,0,sizeof(K));
memset(X,0,sizeof(X));
memset(Y,0,sizeof(Y));
memset(Z,0,sizeof(Z));
memset(presum,0,sizeof(presum));
arr.clear();
mp.clear();
ans=0;
cin>>N>>Q;
cin>>X[0]>>X[1]>>A[0]>>B[0]>>C[0]>>M[0];
cin>>Y[0]>>Y[1]>>A[1]>>B[1]>>C[1]>>M[1];
cin>>Z[0]>>Z[1]>>A[2]>>B[2]>>C[2]>>M[2];
for(int i=2;i<N;i++)
{
X[i]=(A[0]*X[i-1]+B[0]*X[i-2]+C[0])%M[0];
Y[i]=(A[1]*Y[i-1]+B[1]*Y[i-2]+C[1])%M[1];
if(X[i]<0)
{
cout<<X[i]<<endl;
}
if(Y[i]<0)
{
cout<<Y[i]<<endl;
}
}
// return 0;
for(int i=2;i<Q;i++)
{
Z[i]=(A[2]*Z[i-1]+B[2]*Z[i-2]+C[2])%M[2];
}
for(int i=0;i<N;i++)
{
L[i]=min(X[i],Y[i])+1;
R[i]=max(X[i],Y[i])+1;
}
for(int i=0;i<Q;i++)
{
K[i]=Z[i]+1;
}
//test [1,3),[5,7)
// N=2;
// L[0]=1;
// L[1]=5;
// R[0]=2;
// R[1]=6;
// Q=6;
// K[0]=1;
// K[1]=2;
// K[2]=3;
// K[3]=4;
// K[4]=5;
// K[5]=6;
// for(int i=0;i<N;i++)
// {
// cout<<L[i]<<" ";
// }
// cout<<endl;
// for(int i=0;i<N;i++)
// {
// cout<<R[i]<<" ";
// }
// cout<<endl;
// for(int i=0;i<Q;i++)
// {
// cout<<K[i]<<" ";
// }
// cout<<endl;
for(int i=0;i<N;i++)
{
arr.push_back(make_pair(L[i],1));
arr.push_back(make_pair(R[i]+1,-1));//[left,right)
}
sort(arr.begin(),arr.end(),cmp);
int cnt=0;
for(int i=0;i<arr.size();i++)
{
cnt+=arr[i].second;
mp[arr[i].first]=cnt;
}
// cout<<"here"<<endl;
// int idx=0;
// auto preiter=mp.begin();
// for(auto iter=mp.begin();iter!=mp.end();iter++)
// {
cout<<iter->first<<" "<<iter->second<<endl;
// if(iter->first<0)
// {
// cout<<iter->first<<endl;
// }
// if(iter==mp.begin())
// {
// presum[idx++]=make_pair(iter->first,iter->second);
// }
// else
// {
// presum[idx]=make_pair(iter->first,presum[idx-1].second+(iter->first-presum[idx-1].first-1)*preiter->second+iter->second);
if(iter->second==0)
{
presum[idx].first--;
}
// idx++;
presum[iter->first]=presum[preiter->first]+(iter->first-preiter->first-1)*preiter->second+iter->second;
// }
if(presum[idx-1].first<0)
{
cout<<presum[idx-1].first<<endl;
}
// preiter=iter;
// }
// auto preiter=mp.end();
int idx=mp.size()-1;//total number of scores
for(map<long long,long long>::reverse_iterator iter=mp.rbegin();iter!=mp.rend();iter++)
{
// cout<<iter->first<<" "<<iter->second<<endl;
if(iter->first<0)
{
cout<<iter->first<<endl;
}
if(iter==mp.rbegin())
{
suffixsum[idx]=make_pair(iter->first,iter->second);
}
else
{
suffixsum[idx]=make_pair(iter->first,suffixsum[idx+1].second+(suffixsum[idx+1].first-iter->first-1)*iter->second+iter->second);
// presum[iter->first]=presum[preiter->first]+(iter->first-preiter->first-1)*preiter->second+iter->second;
}
idx--;
// if(presum[idx-1].first<0)
// {
// cout<<presum[idx-1].first<<endl;
// }
// preiter=iter;
}
// cout<<"suffix array"<<endl;
// for(int i=0;i<mp.size();i++)
// {
// cout<<suffixsum[i].first<<" "<<suffixsum[i].second<<endl;
// }
// continue;
// for(int i=0;i<idx;i++)
// {
// cout<<presum[i].first<<" "<<presum[i].second<<endl;
// }
// int total=presum[idx-1].second;
cout<<total<<endl;
// for(int i=0;i<Q;i++)
// {
// if(K[i]>total)
// {
// continue;
// }
// int target=total-K[i]+1;
// int tmp=lower_bound(presum,presum+idx,make_pair(-1,target),searchcmp)-presum;//return the last x with x<=target
// cout<<"tmp "<<tmp<<" "<<presum[tmp].first<<" "<<presum[tmp].second<<endl;
// cout<<mp[presum[tmp-1].first]<<endl;
// if(tmp==0)
// {
// cout<<"error"<<endl;
// }
// if(presum[tmp].second==target||presum[tmp].second-target<mp[presum[tmp-1].first])
// {
// ans+=(i+1)*presum[tmp].first;
// cout<<i<<" here1 "<<presum[tmp].first<<endl;
// }
// else
// {
// int gap=target-presum[tmp-1].second-1;
// int val=presum[tmp-1].first+1+gap/mp[presum[tmp-1].first];
// ans+=(i+1)*val;
// cout<<i<<" here2 "<<val<<endl;
// }
//
// }
for(int i=0;i<Q;i++)
{
// cout<<K[i]<<" "<<suffixsum[0].second<<endl;
if(K[i]>suffixsum[0].second)
{
continue;
}
long long target=K[i];
// cout<<"target "<<target<<endl;
long long tmp=lower_bound(suffixsum,suffixsum+mp.size(),make_pair((long long)-1,target),searchcmp)-suffixsum;//return the first x with x<=target
// cout<<"tmp "<<tmp<<" "<<suffixsum[tmp].first<<" "<<suffixsum[tmp].second<<endl;
// cout<<mp[presum[tmp-1].first]<<endl;
// if(tmp==0)
// {
// cout<<"error"<<endl;
// }
if(suffixsum[tmp].second==target)//||suffixsum[tmp].second-mp[suffixsum[tmp+1].first]<)
{
ans+=(i+1)*suffixsum[tmp].first;
// cout<<i<<" here1 "<<suffixsum[tmp].first<<endl;
}
else
{
long long gap=target-suffixsum[tmp].second-1;
// cout<<"gap "<<gap<<endl;
// cout<<suffixsum[tmp-1].first<<" "<<mp[suffixsum[tmp-1].first]<<endl;
long long val=suffixsum[tmp].first-1-gap/mp[suffixsum[tmp-1].first];
// cout<<"val "<<val<<endl;
ans+=(i+1)*val;
// cout<<i<<" here2 "<<val<<endl;
}
}
printf("Case #%d: %lld\n",ca,ans);
cerr<<"finish case "<<ca<<endl;
}
FINISH_TIME=clock();
cerr<<1.0*(FINISH_TIME-START_TIME)/CLOCKS_PER_SEC <<" (s) "<<endl;
return 0;
}