Description
最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。
超级计算机中的任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行),其优先级为Pi。同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同。调度系统会经常向查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个)的优先级之和是多少。特别的,如果Ki大于第Xi秒正在运行的任务总数,则直接回答第Xi秒正在运行的任务优先级之和。上述所有参数均为整数,时间的范围在1到n之间(包含1和n)。
Input
输入文件第一行包含两个空格分开的正整数m和n,分别表示任务总数和时间范围。
接下来m行,每行包含三个空格分开的正整数Si、Ei和Pi(Si≤Ei),描述一个任务。
接下来n行,每行包含四个空格分开的整数Xi、Ai、Bi和Ci,描述一次查询。查询的参数Ki需要由公式 Ki=1+(Ai*Pre+Bi) mod Ci
计算得到。其中Pre表示上一次查询的结果,对于第一次查询,Pre=1。
Output
输出共n行,每行一个整数,表示查询结果。
优先级离散化后,按时间顺序向可持久化线段树插入/删除任务的优先级,同时维护子树中任务个数。
#include<cstdio> #include<algorithm> typedef long long lint; const int N=20000000,mx=131072; int m,n; struct op{ int t,v; bool s; op(){} op(int t_,int v_,bool s_):t(t_),v(v_),s(s_){} }; bool operator<(op a,op b){ return a.t<b.t; } op ops[200005]; int opp=0; int vs[100005],vp=0; int lc[N],rc[N],sz[N]; lint sum[N]; int rts[100005]; int p=1; lint get(int w,int x,int L,int R){ //printf("g[%d,%d] x:%d\n",L,R,x); int M=L+R>>1; if(sz[w]<=x)return sum[w]; if(L==R)return vs[L-1]*1ll*x; if(sz[lc[w]]>=x)return get(lc[w],x,L,M); return sum[lc[w]]+get(rc[w],x-sz[lc[w]],M+1,R); } int add(int w,int v,bool s,int x,int L,int R){ //printf("[%d,%d] v:%d s:%d x:%d\n",L,R,v,(int)s,x); int u=p++; if(L==R){ if(s){ sz[u]=sz[w]+1; sum[u]=sum[w]+v; }else{ sz[u]=sz[w]-1; sum[u]=sum[w]-v; } lc[u]=rc[u]=0; }else{ int M=L+R>>1; if(x>M){ rc[u]=add(rc[w],v,s,x,M+1,R); lc[u]=lc[w]; }else{ lc[u]=add(lc[w],v,s,x,L,M); rc[u]=rc[w]; } sz[u]=sz[lc[u]]+sz[rc[u]]; sum[u]=sum[lc[u]]+sum[rc[u]]; } return u; } int build(int L,int R){ int w=p++; int M=L+R>>1; if(L<R){ lc[w]=build(L,M); rc[w]=build(M+1,R); } sz[w]=sum[w]=0; return w; } int main(){ int a,b,c,x; lint pre=1ll; scanf("%d%d",&m,&n); for(int i=0;i<m;i++){ scanf("%d%d%d",&a,&b,&c); ops[opp++]=op(a,c,1); ops[opp++]=op(b+1,c,0); vs[vp++]=c; } std::sort(ops,ops+opp); std::sort(vs,vs+vp); int vm=vp;vp=1; for(int i=1;i<vm;i++)if(vs[i]>vs[i-1])vs[vp++]=vs[i]; rts[0]=build(1,mx); for(int i=1,oi=0;i<=n;i++){ rts[i]=rts[i-1]; while(oi<opp&&ops[oi].t==i){ rts[i]=add(rts[i],ops[oi].v,ops[oi].s,std::upper_bound(vs,vs+vp,ops[oi].v)-vs,1,mx); oi++; } } for(int i=1;i<=n;i++){ scanf("%d%d%d%d",&x,&a,&b,&c); pre=get(rts[x],(a*pre%c+b)%c+1,1,mx); printf("%lld\n",pre); } return 0; }