1. 程式人生 > >P3168 [CQOI2015]任務查詢系統

P3168 [CQOI2015]任務查詢系統

每次 如果 sam space r+ include name 修改 優先級

題目描述

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

輸入輸出樣例

輸入樣例#1: 復制
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
輸出樣例#1: 復制
2
8
11

說明

樣例解釋

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的一個排列

題解

需要用差分數組

總而言之就是令$b[i]=a[i]-a[i-1]$

於是$\sum_{i=1}^n b[i]=a[i]$

可以通過前綴和來查詢單個位置的值

每一個任務,就是給區間$[l,r]$每一個位置加上優先級$k$

等價於$b[l]+=k,b[r+1]-=k$

然後可以對每一個位置存下每個修改,然後在每個位置建主席樹

記錄下每個位置最後修改後所建主席樹的編號,查詢時直接使用

 1 //minamoto
 2 #include<bits/stdc++.h>
 3 #define ll long long
 4 using namespace std;
 5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 6 char buf[1<<21],*p1=buf,*p2=buf;
 7 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
 8 inline int read(){
 9     #define num ch-‘0‘
10     char ch;bool flag=0;int res;
11     while(!isdigit(ch=getc()))
12     (ch==-)&&(flag=true);
13     for(res=num;isdigit(ch=getc());res=res*10+num);
14     (flag)&&(res=-res);
15     #undef num
16     return res;
17 }
18 char obuf[1<<24],*o=obuf;
19 void print(ll x){
20     if(x>9) print(x/10);
21     *o++=x%10+48;
22 }
23 const int N=2e5+5,M=5e6+5;
24 int L[M],R[M],num[M],rt[N],spj[N<<1];ll sum[M];
25 /*根據題意 1 <= Pi <= 10000000
26 按照權值線段樹的定義空間顯然是不夠的
27 但考慮一共只有2m次插入,每次只增加log2m個節點
28 所以我們這麽開是沒有問題的*/
29 int ver[N<<1],Next[N<<1],head[N];
30 int n,q,cnt=0,tot=0,fx,m;ll ans=1;
31 void add(int u,int e){
32     ver[++tot]=e,Next[tot]=head[u],head[u]=tot;
33 }
34 void update(int last,int &now,int l,int r,int x){
35     if(!now) now=++cnt;
36     num[now]=num[last]+(x<0?-1:1),sum[now]=sum[last]+x;
37     /*因為用了差分數組,如果x為負說明少了一個數*/
38     if(l==r) return;
39     int mid=(l+r)>>1;
40     if(abs(x)<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x);
41     else L[now]=L[last],update(R[last],R[now],mid+1,r,x);
42 }
43 ll query(int u,int l,int r,int k){
44     if(l==r) return l*k;
45     int mid=(l+r)>>1;
46     if(k<=num[L[u]]) return query(L[u],l,mid,k);
47     else return query(R[u],mid+1,r,k-num[L[u]])+sum[L[u]];
48 }
49 int main(){
50     //freopen("testdata.in","r",stdin);
51     n=read(),q=read();
52     for(int i=1;i<=n;++i){
53         int u=read(),v=read(),e=read();
54         add(u,e),add(v+1,~e+1),cmax(fx,e);
55     }
56     for(int u=1;u<=n;++u){
57         for(int i=head[u];i;i=Next[i])
58         ++m,update(rt[m-1],rt[m],1,fx,ver[i]);
59         spj[u]=m;
60     }
61     while(q--){
62         int a,b,c,x;
63         x=read(),a=read(),b=read(),c=read();
64         ll k=(1ll*a*ans+b)%c+1;
65         int w=rt[spj[x]];
66         print(ans=(num[w]<=k)?sum[w]:query(w,1,fx,k));
67         *o++=\n;
68     }
69     fwrite(obuf,o-obuf,1,stdout);
70     return 0;
71 }

P3168 [CQOI2015]任務查詢系統