1. 程式人生 > >【CQOI2015】 任務查詢系統 (主席樹)

【CQOI2015】 任務查詢系統 (主席樹)

names 輸入輸出格式 輸出 正整數 當前 getc printf scanf 大於

luogu & bzoj

題目描述

最近實驗室正在為其管理的超級計算機編制一套任務管理系統,而你被安排完成其中的查詢部分。超級計算機中的任務用三元組(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。

輸出格式:

輸出共n行,每行一個整數,表示查詢結果。

解題思路

當然,看到區間k大的時候自然而然就會想到主席樹,而每一個任務是一個時間的區間,因為主席樹自帶差分的功能(在前面差分,後面的所有點不需要從頭掃描一遍!!),所以,我們可以按照時間為根節點建立主席樹,樹上的每一個節點維護的是優先級,數據有當前區間內的個數和優先級的和。

代碼

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<math.h>
 6 #define LL long long
 7 using namespace std;
 8 const int maxn=(1e5+10)*85;
 9 struct nod{
10     int pos,val;
11 };
12 nod p[maxn];
13 LL root[maxn];
14 LL sum[maxn],num[maxn],lson[maxn],rson[maxn]; 15 int end[maxn],num_start[maxn]; 16 int n,m,cntt=0,cnt=1; 17 inline bool cmp(nod a,nod b){ 18 return a.pos<b.pos; 19 } 20 inline void read(long long &x){ 21 x=0; register char ch=getchar(); 22 while(ch<0||ch>9)ch=getchar(); 23 while(ch>=0&&ch<=9)x=x*10+ch-0,ch=getchar(); 24 } 25 inline int ins(LL &ID,LL IDl,int nl,int nr,int val){ 26 if(ID==0)ID=++cnt; 27 if(val>0)num[ID]=num[IDl]+1; 28 else num[ID]=num[IDl]-1; 29 sum[ID]=sum[IDl]+val; 30 if(nl==nr)return 0; 31 int m=(nl+nr)>>1; 32 if(m>=abs(val)){ 33 rson[ID]=rson[IDl]; 34 ins(lson[ID],lson[IDl],nl,m,val); 35 } 36 else { 37 lson[ID]=lson[IDl]; 38 ins(rson[ID],rson[IDl],m+1,nr,val); 39 } 40 num[ID]=num[lson[ID]]+num[rson[ID]]; 41 sum[ID]=sum[lson[ID]]+sum[rson[ID]]; 42 } 43 inline LL query(int nl,int nr,int now,int k){ 44 if(nl==nr)return (LL)nl*k; 45 int m=(nl+nr)>>1; 46 if(num[lson[now]]>=k)return query(nl,m,lson[now],k); 47 else return query(m+1,nr,rson[now],k-num[lson[now]])+sum[lson[now]]; 48 } 49 int main(){ 50 int max_val=-99999999; 51 scanf("%d%d",&m,&n); 52 register int S,E,P; 53 for(register int i=1;i<=m;i++){ 54 scanf("%d%d%d",&S,&E,&P); 55 p[++cntt].pos=S; p[cntt].val=P; 56 p[++cntt].pos=E+1; p[cntt].val=-P; 57 max_val=max(max_val,P); 58 } 59 sort(p+1,p+cntt+1,cmp); 60 root[0]=1; 61 for(register int i=1;i<=cntt;i++) 62 ins(root[i],root[i-1],1,max_val,p[i].val); 63 for(register int i=cntt;i>=0;i--) 64 if(p[i].pos!=p[i+1].pos)end[p[i].pos]=i; 65 for(register int i=1;i<=1e6;i++) 66 if(!end[i])end[i]=end[i-1]; 67 register long long X,A,B,C,K,pre=1; 68 for(register int i=1;i<=n;i++){ 69 read(X),read(A),read(B),read(C); 70 K=1+(A*pre+B)%C; 71 if(num[root[end[X]]]<=K)pre=sum[root[end[X]]]; 72 else pre=query(1,max_val,root[end[X]],K); 73 printf("%lld\n",pre); 74 } 75 }

【CQOI2015】 任務查詢系統 (主席樹)