最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。
超级计算机中的任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行),其优先级为Pi。同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同。调度系统会经常向查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个)的优先级之和是多少。特别的,如果Ki大于第Xi秒正在运行的任务总数,则直接回答第Xi秒正在运行的任务优先级之和。上述所有参数均为整数,时间的范围在1到n之间(包含1和n)。
输入文件第一行包含两个空格分开的正整数m和n,分别表示任务总数和时间范围。
接下来m行,每行包含三个空格分开的正整数Si、Ei和Pi(Si≤Ei),描述一个任务。
接下来n行,每行包含四个空格分开的整数Xi、Ai、Bi和Ci,描述一次查询。查询的参数Ki需要由公式 Ki=1+(Ai*Pre+Bi) mod Ci
计算得到。其中Pre表示上一次查询的结果,对于第一次查询,Pre=1。
样例解释
K1 = (1*1+3)%2+1 = 1
K2 = (1*2+3)%4+1 = 2
K3 = (2*8+4)%3+1 = 3
对于100%的数据,1≤m,n,Si,Ei,Ci≤100000,0≤Ai,Bi≤100000,1≤Pi≤10000000,Xi为1到n的一个排列
以时刻为下标,优先级为区间建主席树。对于在一个区间[l,r]内存在的任务,在l处出现次数加1,在r+1处出现次数减1,把这些看作事件,将时刻i所有发生的时间加入i的线段树。然后就可以在T[x]上统计答案了。
1 #include<cmath>
2 #include<queue>
3 #include<vector>
4 #include<cstdio>
5 #include<cstring>
6 #include<iostream>
7 #include<algorithm>
8 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
9 using namespace std;
10
11 typedef long long ll;
12 const int N = 1e5+10;
13 const int M = 80*N;
14
15 struct Node {
16 int lc,rc,cnt;
17 ll sum;
18 Node() {}
19 }T[M];
20
21 int n,m,sz;
22 int rt[N],mark[M],kase;
23 vector<int> L[N],R[N];
24
25 ll read() {
26 char c=getchar();
27 ll f=1,x=0;
28 while(!isdigit(c)) {
29 if(c=='-') f=-1; c=getchar();
30 }
31 while(isdigit(c))
32 x=x*10+c-'0',c=getchar();
33 return x*f;
34 }
35
36 void newnode(int& y,int x)
37 {
38 T[y=++sz]=T[x]; mark[y]=kase;
39 }
40 void update(int l,int r,int x,int& y,int v,int c)
41 {
42 if(mark[x]!=kase)
43 newnode(y,x);
44 T[y].cnt+=c; T[y].sum+=v*c;
45 if(l==r) return ;
46 int mid=(l+r)>>1;
47 if(v<=mid) update(l,mid,T[x].lc,T[y].lc,v,c);
48 else update(mid+1,r,T[x].rc,T[y].rc,v,c);
49 }
50 ll query(int l,int r,int x,int rk)
51 {
52 if(l==r) return (ll)l*rk;
53 int mid=(l+r)>>1;
54 if(T[T[x].lc].cnt>=rk) return query(l,mid,T[x].lc,rk);
55 else return query(mid+1,r,T[x].rc,rk-T[T[x].lc].cnt)+T[T[x].lc].sum;
56 }
57 int main()
58 {
59 //freopen("in.in","r",stdin);
60 //freopen("out.out","w",stdout);
61 n=read(),m=read();
62 int s,e,p,mn=1e9,mx=-1e9;
63 FOR(i,1,n) {
64 s=read(),e=read(),p=read();
65 mn=min(mn,s),mx=max(mx,e);
66 L[s].push_back(p); R[e].push_back(p);
67 }
68 FOR(i,mn,mx) {
69 newnode(rt[i],rt[i-1]); ++kase;
70 FOR(j,0,(int)L[i].size()-1) {
71 update(1,1e7,rt[i],rt[i],L[i][j],1);
72 }
73 FOR(j,0,(int)R[i-1].size()-1)
74 update(1,1e7,rt[i],rt[i],R[i-1][j],-1);
75 }
76 int x; ll a,b,c,pre=1;
77 FOR(i,1,m) {
78 x=read(),a=read(),b=read(),c=read();
79 int k=(int) 1+(a*pre+b)%c;
80 if(T[rt[x]].cnt<=k) printf("%lld\n",pre=T[rt[x]].sum);
81 else printf("%lld\n",pre=query(1,1e7,rt[x],k));
82 }
83 return 0;
84 }