Problem B. Combining Classes Google Kickstart Round G 2018

题意:每个班级的分数是[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;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值