bzoj 3932 [CQOI2015]任务查询系统(主席树)

 

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行,每行一个整数,表示查询结果。
 

Sample Input

4 3
1 2 6
2 3 3
1 3 2
3 3 4
3 1 3 2
1 1 3 4
2 2 4 3

Sample Output

2
8
11

HINT

 

样例解释

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]上统计答案了。

       需要注意的是时刻是连续的,所以每一个时刻都要先把上一个时刻的T复制过来。

 

【代码】

 

 

 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 }

 

你可能感兴趣的:(bzoj 3932 [CQOI2015]任务查询系统(主席树))