ZOJ 3940

一个很暴力的递归拆分过程改成priority_queue就过了,醉了

#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
using namespace std;

typedef long long ll;
typedef long long LL;
const int mod = 1e9 + 7;

const int N = 1e5 + 100;
int a[N] , n ,m;
int cnt[N],min_;
struct San :vector<int>{
    void prepare(){
         sort(begin(),end());
         erase(unique(begin(),end()),end());
    }
    int get_l(int x){
        return (int)(lower_bound(begin(),end(),x)-begin())+1;
    }
    int get_r(int x){
        return (int)(upper_bound(begin(),end(),x)-begin())+1-1;
    }
}id;
vector<pair<int,int> > v;
int all = 0;
struct node{
    int x , y;
    node(){}
    node(int x , int y):x(x),y(y){}
    bool operator <(const node& rhs)const{
       return x < rhs.x;
    }
};
void cal(int p,int max_ , int num){
     priority_queue<node> Q;
     Q.push(node(m  , 1));
     for(int i = 1 ; i<=n; i++){
          int x  = a[i] , cnt = 0;
          while(Q.top().x >= x){
                node u = Q.top(); Q.pop();
                Q.push(node(x - 1 , ((u. x + 1)/x) * u.y));
                if((u.x + 1)% x)
                    Q.push(node((u.x + 1)% x - 1 , u.y));
          }
     }
     while(!Q.empty()){
          node u = Q.top(); Q.pop();
          all += u.y;
          v.push_back(make_pair(u.x , u.y));
     }
}
int query[N],ans[N];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
    scanf("%d %d",&n,&m);
    min_= mod + 1;
    for(int i =1;i<=n;i++) scanf("%d",&a[i]),min_ = min(min_ , a[i]);
    int Q; scanf("%d",&Q);
    id.clear();
    for(int i =1;i<=Q;i++){
        int y;
        scanf("%d",&query[i]);
        id.push_back(query[i]);
    }
    id.prepare();
    v.clear();
    all =0;
    cal(1 ,  m + 1 , 1);
    sort(v.begin(),v.end());
    int pos = 0;
    for(int i = 0 ; i<id.size() ; i++){
          while(pos < v.size() && v[pos].first  < id[i]){
               all-=v[pos].second;
               ++pos;
          }
          ans[i + 1] = all;
    }
    int Ans =0;
    for(int i = 1 ; i<=Q; i++){
        Ans = (Ans + (ll)i * ans[id.get_l(query[i])] % mod) % mod;
    }
    printf("%d\n",Ans);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值