任務查詢系統[主席樹]
阿新 • • 發佈:2018-11-04
題目描述
最近實驗室正在為其管理的超級計算機編制一套任務管理系統,而你被安排完成其中的查詢部分。超級計算機中的任務用三元組(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的一個排列
分析
對於區間(l,r)加一個值,我們看做l加一個值,r+1減一個值
主席樹就可以做了
#include<bits/stdc++.h> #define N 200005 #define LL long long using namespace std; int n,m,ret,tot,d,hash[N],rt[N];LL Pre=1; struct Node{int pos,val,delta;}a[N]; struct Tree{int l,r,size;LL val;}t[N*20]; int read(){ int cnt=0,f=1;char ch=0; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar(); return cnt*f; } bool cmp(Node a,Node b){return a.pos<b.pos;} void build(int &o,int l,int r){ o=++tot; if(l==r) return; int mid=l+r>>1; build(t[o].l,l,mid); build(t[o].r,mid+1,r); } void update(int &o,int l,int r,int pos,int pre,int delta){ o=++tot; t[o].l=t[pre].l , t[o].r=t[pre].r; t[o].val = t[pre].val + (LL)(hash[pos] * delta); t[o].size = t[pre].size + delta; if(l==r) return; int mid=l+r>>1; if(pos<=mid) update(t[o].l , l , mid , pos , t[pre].l , delta); else update(t[o].r , mid+1 , r , pos , t[pre].r , delta); } LL quary(int o,int l,int r,int k){ if(l==r) return (LL)t[o].val/t[o].size*k; int sl=t[t[o].l].size,mid=(l+r)>>1; LL ans=0; if(k<=sl) return quary(t[o].l,l,mid,k); else return t[t[o].l].val+quary(t[o].r,mid+1,r,k-sl); } int main(){ int m=read(),n=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(),z=read(); a[++ret].pos=x,a[ret].val=z,a[ret].delta=1; a[++ret].pos=y+1,a[ret].val=z,a[ret].delta=-1; hash[i]=z; } sort(hash+1,hash+m+1); sort(a+1,a+ret+1,cmp); d=unique(hash+1,hash+m+1)-(hash+1); build(rt[0],1,d); for(int i=1;i<=ret;i++){ int x=lower_bound(hash+1,hash+m+1,a[i].val)-hash; int now=a[i].pos; if(now==a[i-1].pos) update(rt[now] , 1 , d , x , rt[now] , a[i].delta); else{ if(i!=1) for(int j=a[i-1].pos+1;j<now;j++) rt[j]=rt[j-1]; update(rt[now] , 1 , d , x , rt[now-1] , a[i].delta); } } for(int i=1;i<=n;i++){ int x=read(),A=read(),B=read(),C=read(); LL k=1+(LL)(A*Pre+B)%C; if(k>=t[rt[x]].size) Pre=t[rt[x]].val; else Pre=quary(rt[x],1,d,k); printf("%lld\n",Pre); } }