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

时间:2021-11-08 14:19:14

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<?-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=;
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>?:-); 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+,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+,r,k-siz[lc[o]]);
}
int main(){
register int i,j; int q1,q2,q3,q4;
scanf("%d%d",&n,&m);
for(i=;i<=n;++i){
scanf("%d%d%d",&q1,&q2,&q3);
g[q1].push_back(q3);
g[q2+].push_back(-q3);
mx=Max(mx,q3);
}
for(i=;i<=n;++i){
for(j=g[i].size()-;j>=;--j)
++tot,Ins(rt[tot],rt[tot-],,mx,g[i][j]);
ti[i]=tot;
}
for(i=;i<=m;++i){
scanf("%d%d%d%d",&q1,&q2,&q3,&q4);
q2=+(q2*Pre+q3)%q4; q1=rt[ti[q1]];
Pre=q2<siz[q1]?Ask(q1,,mx,q2):s[q1];
printf("%lld\n",Pre);
}return ;
}