题链:
https://www.luogu.org/problemnew/show/P3168
题解:
主席树
强制在线?
那就直接对每一个前缀时间建一个线段树(可持久化线段树),线段树维护优先度权值。
代码:
#include<bits/stdc++.h> #define MAXN 100005 using namespace std; int tmp[MAXN]; int N,M,tnt; long long pre=1; struct Event{ int ent; int p[MAXN*2],k[MAXN*2],nxt[MAXN*2],head[MAXN]; Event():ent(2){} void Add(int _t,int _p,int _k){ p[ent]=_p; k[ent]=_k; nxt[ent]=head[_t]; head[_t]=ent++; } }E; struct SGT{//可持久化线段树(主席树),单修,区查??? int idnt,root[MAXN]; int ls[MAXN*18*2],rs[MAXN*18*2],size[MAXN*18*2]; long long sum[MAXN*18*2]; void Pushup(int u){ size[u]=size[ls[u]]+size[rs[u]]; sum[u]=sum[ls[u]]+sum[rs[u]]; } void Modify(int v,int &u,int l,int r,int p,int k){ u=++idnt; ls[u]=ls[v]; rs[u]=rs[v]; sum[u]=sum[v]; size[u]=size[v]; if(l==r) return (void)(sum[u]+=k*tmp[l],size[u]+=k); int mid=(l+r)>>1; if(p<=mid) Modify(ls[v],ls[u],l,mid,p,k); else Modify(rs[v],rs[u],mid+1,r,p,k); Pushup(u); } long long Query(int u,int l,int r,int k){//先特判k是否太大 if(l==r){return 1ll*k*tmp[l];} int mid=(l+r)>>1; if(size[ls[u]]>=k) return Query(ls[u],l,mid,k); long long ret=sum[ls[u]]; ret+=Query(rs[u],mid+1,r,k-size[ls[u]]); return ret; } }DT; int main(){ scanf("%d%d",&M,&N); int a,b,c,x,k; for(int i=1;i<=M;i++){ scanf("%d%d%d",&a,&b,&c); E.Add(a,c,1); E.Add(b+1,c,-1); tmp[++tnt]=c; } sort(tmp+1,tmp+tnt+1); tnt=unique(tmp+1,tmp+tnt+1)-tmp-1; for(int i=1,last=0;i<=N;i++){ DT.root[i]=last; for(int e=E.head[i];e;e=E.nxt[e]){ E.p[e]=lower_bound(tmp+1,tmp+tnt+1,E.p[e])-tmp; DT.Modify(last,DT.root[i],1,tnt,E.p[e],E.k[e]); last=DT.root[i]; } } for(int i=1;i<=N;i++){ scanf("%d%d%d%d",&x,&a,&b,&c); k=1+(a*pre+b)%c;//*/scanf("%d%d",&x,&k); if(DT.size[DT.root[x]]<=k) pre=DT.sum[DT.root[x]]; else pre=DT.Query(DT.root[x],1,tnt,k); printf("%lld ",pre); } return 0; }