思路:这题要求强制在线,我们先来考虑一下离线的时候该怎么写
首先,他要求前ki个的和 所以我们要维护现在在执行的任务个数,其次就是任务优先级的总和(显然要离散化)
然后我们可以把询问按照时间排序,这样的话根据任务开始和结束的时间 进行增或者删的操作(类似扫描线)
就可以得到某一时间需要查询的答案了
可是这个问题得在线,所以我们得用主席树来记录每个时间点的线段树,再询问就行啦
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
typedef long long ll;
struct as{
int l,r,val;
}a[N];
struct node{
int pos,ct,t;
}q[N<<1];
struct Tree{
int lc,rc;
ll sum,cnt;
}tree[N*50];
int b[N],root[N];
int tot;
ll y,d,c,k,x;
void update(int &now,int last,int l,int r,int pos,int f){
now = ++tot;
tree[now] = tree[last];
tree[now].cnt+=f;
tree[now].sum+=1LL*f*b[pos];
if(l == r) return;
int mid = l+r>>1;
if(pos<=mid) update(tree[now].lc,tree[last].lc,l,mid,pos,f);
else update(tree[now].rc,tree[last].rc,mid+1,r,pos,f);
}
ll query(int now,int l,int r,int k){
if(l == r) return tree[now].sum*k/tree[now].cnt;
int mid = l+r>>1;
int cn = tree[tree[now].lc].cnt;
if(tree[now].cnt<=k) return tree[now].sum;
if(k<=cn) return query(tree[now].lc,l,mid,k);
else return tree[tree[now].lc].sum+query(tree[now].rc,mid+1,r,k-cn);
}
bool cmp(node a,node b){//按时间排序
return a.t<b.t;
}
int n,m;
int main(){
scanf("%d%d",&m,&n);
for(int i = 1; i <= m; i++){
scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].val);
b[i] = a[i].val;
}
sort(b+1,b+1+m);
int p = unique(b+1,b+1+m)-b-1;
for(int i = 1; i <= m; i++){
int pos = lower_bound(b+1,b+1+p,a[i].val)-b;
q[i*2-1] = (node){pos,1,a[i].l};
q[i*2] = (node){pos,-1,a[i].r+1};
}
sort(q+1,q+1+2*m,cmp);
int id = 1;
for(int i = 1; i <= n; i++){
root[i] = root[i-1];
while(q[id].t == i){
update(root[i],root[i],1,p,q[id].pos,q[id].ct);
id++;
}
}
ll ans = 1;
for(int i = 1; i <= n; i++){
scanf("%lld%lld%lld%lld",&x,&y,&d,&c);
k = 1+(y*ans+d)%c;
//printf("x = %lld root[x] = %d\n",x,root[x]);
ans = query(root[x],1,p,k);
printf("%lld\n",ans);
}
return 0;
}