bzoj3932 / P3168 [CQOI2015]任务查询系统(主席树+差分)

P3168 [CQOI2015]任务查询系统

看到第k小,就是主席树辣

对于每一段任务(a,b,k),在版本a的主席树+k,版本b+1的主席树-k

同一时间可能有多次修改,所以开个vector存操作,再开个数组ti[p]保存时间点p最终的版本号

注意long long

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
inline int Abs(int a){return a<0?-a:a;}
inline int Max(int a,int b){return a>b?a:b;}
#define N 100005
#define W 20000005
int n,m,mx,u,tot,ti[N],rt[W],lc[W],rc[W],siz[W];
ll s[W],Pre=1;
vector <int> g[N];
#define mid (l+r)/2
void Ins(int &o,int p,int l,int r,int v){
    o=++u; siz[o]=siz[p]+(v>0?1:-1); s[o]=s[p]+v;
    if(l==r) return ;
    if(Abs(v)<=mid) rc[o]=rc[p],Ins(lc[o],lc[p],l,mid,v);
    else lc[o]=lc[p],Ins(rc[o],rc[p],mid+1,r,v);
}
ll Ask(int o,int l,int r,int k){
    if(l==r) return 1ll*l*k;
    if(siz[lc[o]]>k) return Ask(lc[o],l,mid,k);
    else return s[lc[o]]+Ask(rc[o],mid+1,r,k-siz[lc[o]]);
}
int main(){
    register int i,j; int q1,q2,q3,q4;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;++i){
        scanf("%d%d%d",&q1,&q2,&q3);
        g[q1].push_back(q3);
        g[q2+1].push_back(-q3);
        mx=Max(mx,q3);
    }
    for(i=1;i<=n;++i){
        for(j=g[i].size()-1;j>=0;--j)
            ++tot,Ins(rt[tot],rt[tot-1],1,mx,g[i][j]);
        ti[i]=tot;
    }
    for(i=1;i<=m;++i){
        scanf("%d%d%d%d",&q1,&q2,&q3,&q4);
        q2=1+(q2*Pre+q3)%q4; q1=rt[ti[q1]];
        Pre=q2<siz[q1]?Ask(q1,1,mx,q2):s[q1];
        printf("%lld\n",Pre);
    }return 0;
}

 

posted @ 2019-03-26 19:33  kafuuchino  阅读(113)  评论(0编辑  收藏  举报