BZOJ 3932

其实多一个(或者两个) lg(n) 的代码还是挺快的……

本题比较快的一个实现是主席树 , 第一次写 , 模版时间并不理想 , 优化时间这玩意就当作留一个坑以后填罢

主席树版代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <cassert>

using namespace std;
const int maxn = 1e5+1e2;
const int INF = 0x3f3f3f3f;
typedef long long ll;

int n , m;
int s[maxn] , e[maxn] , p[maxn];

__inline int re() {
    int n = 0, ch = getchar(); bool flag = false;
    while(!isdigit(ch)) flag |= ch == '-', ch = getchar();
    while(isdigit(ch)) n = n * 10 + ch - '0', ch = getchar();
    return flag ? -n : n;
}

vector<int> as;
void concrete()
{
    for(int i=1;i<=n;i++) as.push_back(p[i]);
    sort(as.begin() , as.end());
    as.erase(unique(as.begin() , as.end()) , as.end());

    for(int i=1;i<=n;i++) p[i] = lower_bound(as.begin() , as.end() , p[i]) - as.begin();
}

struct node
{
    node* ch[2];
    ll num , s;

    node(){ s = num = 0; }
    void maintain() { s = ch[0]->s + ch[1]->s; num = ch[0]->num + ch[1]->num; }  
};

node pool[maxn*100]; int CNT;
node* null = new node();
node* root[maxn];

node* newNode()
{
    pool[CNT].ch[0] = pool[CNT].ch[1] = null;
    return &pool[CNT++];
}

node* modify(node* o , int l , int r , int p , int a)
{
    node* res = newNode();
    *res = *o;

    if(l == r) 
    {
        res->num += a;
        res->s += (ll)a*as[l];
        //cout<<as[l]<<endl;
        return res;
    }

    int mid = (l+r)/2;
    if(p <= mid) res->ch[0] = modify(o->ch[0] , l , mid , p , a);
    else res->ch[1] = modify(o->ch[1] , mid+1 , r , p , a);
    res->maintain();
    return res;
}

ll query(node* o , int l , int r , int k)
{
    if(o->num <= k) return o->s;
    if(l==r) return (ll)as[l] * k;

    int mid = (l+r)/2;
    if(o->ch[0]->num >= k) return query(o->ch[0] , l , mid , k);
    else return o->ch[0]->s + query(o->ch[1] , mid+1 , r , k-o->ch[0]->num);
}

struct state
{
    int a , b , c;
    state(int a=0 , int b=0 , int c=0):a(a),b(b),c(c){}
    bool operator <(const state& d)const { return a < d.a; }
};

vector<state> ts;

int main()
{
    null->ch[0] = null->ch[1] = null;
    cin>>n>>m;

    for(int i=1;i<=n;i++) s[i] = re() , e[i] = re() , p[i] = re();
    concrete();

    for(int i=1;i<=n;i++) ts.push_back(state(s[i] , p[i] , 1)) , ts.push_back(state(e[i]+1 , p[i] , -1));
    sort(ts.begin() , ts.end());

    int len = as.size();
    root[0] = null;
    for(int i=1 , j=0;i<=n;i++)
    {
        node* now = root[i-1]; 

        while(j<ts.size() && ts[j].a == i)
        {
            now = modify(now , 0 , len-1 , ts[j].b , ts[j].c);
            j++;
        }
        root[i] = now;
    }

    ll pre = 1 , x , a , b , c , k;
    while(m--)
    {
        x = re(); a = re(); b = re(); c = re();
        k = 1 + (a*pre + b)%c;
        printf("%lld\n" , pre = query(root[x] , 0 , len-1 , k));
    }

    return 0;
}

暴力版代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <cassert>

using namespace std;
typedef long long ll;
const int maxn = 1e5+1e2;

int n , m;
vector<ll> a[maxn*10];
vector<ll> s[maxn*10];
void add(int o , int l , int r , int L , int R , ll added)
{
    if(L <= l && r <= R)
    {
        a[o].push_back(added);
        return;
    }

    int mid = (l+r)/2;
    if(L <= mid) add(o*2 , l , mid , L , R , added);
    if(R >  mid) add(o*2+1 , mid+1 , r , L , R , added);
}

void build(int o , int l , int r)
{
    sort(a[o].begin() , a[o].end());
    s[o].resize(a[o].size());
    for(int i=0;i<a[o].size();i++) s[o][i] = (i==0?0:s[o][i-1]) + a[o][i];

    if(l==r) return;
    else 
    {
        int mid = (l+r)/2;
        build(o*2 , l , mid);
        build(o*2+1 , mid+1 , r);
    }
}

int KKK;
int query(int o , int l , int r , int x , int mx , ll& sum)
{
    int res = upper_bound(a[o].begin() , a[o].end() , mx) - a[o].begin();
    if(res) sum += s[o][res-1];

    if(l==r) return res;
    if(res > KKK) return res;
    int mid =(l+r)/2;
    if(x<=mid) res += query(o*2 , l , mid , x , mx , sum);
    else res += query(o*2+1 , mid+1 , r , x , mx , sum);
    return res;
}
int Max;
ll query(int x , int k)
{
    int l = 0 , r = Max;
    ll res;
    KKK = k;
    while(l+1<r)
    {
        int mid = (l+r)/2;
        if(query(1 , 1 , n , x , mid , res = 0) < k) l = mid;
        else r = mid;
    }

    ll now = query(1 , 1 , n , x , r , res = 0);
    return res - max(now-k , 0LL)*r;
}

int main()
{
    cin>>n>>m;

    for(int i=1;i<=n;i++)
    {
        int a , b , c;
        scanf("%d%d%d" , &a , &b , &c);
        add(1 , 1 , n , a , b , (ll)c);
        Max = max(c , Max);
    }

    build(1 , 1 , n);

    ll pre = 1;
    while(m--)
    {
        ll x , a , b , c , k;
        scanf("%lld%lld%lld%lld" , &x , &a , &b , &c);
        k = 1 + (a*pre+b)%c;
        printf("%lld\n" , pre = query(x , k));
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值