1. 程式人生 > >主席樹||可持久化線段樹||離散化||[CQOI2015]任務查詢系統||BZOJ 3932||Luogu P3168

主席樹||可持久化線段樹||離散化||[CQOI2015]任務查詢系統||BZOJ 3932||Luogu P3168

系統 bool div 一個 記得 排序 事件 while https

題目: [CQOI2015]任務查詢系統

題解:

是一道很經典的題目。大體思路是抓優先級來當下標做主席樹,用時刻作為主席樹的版本。然而優先級範圍到1e7去了,就離散化一遍。然後把每個事件的開始(s)、結束(e)(e記得+1,因為一個事件是第e+1時刻結束的)時間點抓出來排序一遍,按時刻從早到晚維護主席樹。差不多就是這樣。

代碼:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #define ll long long
 6
#define max(a,b) ((a)>(b)?(a):(b)) 7 #define min(a,b) ((a)<(b)?(a):(b)) 8 using namespace std; 9 const int maxn=100000+50,maxm=maxn,maxnum_p=maxm,maxnum_b=maxm<<1; 10 int N,M,cnt_p=0,num_b=0,num_treenode,root[maxnum_b],X,A,B,C,belong_root[maxn]; 11 ll Pre=1,belong[maxm],K; 12 struct _A{int p,s,e,hp;}a[maxm];
13 bool cmp1(const _A&c,const _A&d){return(c.p<d.p);} 14 struct _B{int p,o,data;}b[maxm<<1];//b數組負責記錄把每個時間點都拆出來後的數據 ,data記錄時間點,o是時間點的類型 15 bool cmp2(const _B&c,const _B&d){return(c.data<d.data);} 16 struct Tree{int l,r,ls,rs,cnt;ll sum;}t[(maxnum_p<<2)+maxnum_b*18];
17 void Build(int x,int l,int r){ 18 t[x].l=l;t[x].r=r;int mid=(l+r)>>1; 19 if(l==r)return; 20 Build(t[x].ls=++num_treenode,l,mid);Build(t[x].rs=++num_treenode,mid+1,r); 21 return; 22 } 23 void Update(int u,int x,int p,int o){ 24 int l=t[u].l,r=t[u].r,mid=(l+r)>>1; 25 t[x].l=l;t[x].r=r; 26 if(l==r&&l==p){ 27 if(o==1){t[x].cnt=t[u].cnt+1; t[x].sum=t[u].sum+belong[p];} 28 else{t[x].cnt=t[u].cnt-1; t[x].sum=t[u].sum-belong[p];} 29 return; 30 } 31 if(p<=mid){t[x].rs=t[u].rs; Update(t[u].ls,t[x].ls=++num_treenode,p,o);} 32 else{t[x].ls=t[u].ls; Update(t[u].rs,t[x].rs=++num_treenode,p,o);} 33 t[x].cnt=t[t[x].ls].cnt+t[t[x].rs].cnt; 34 t[x].sum=t[t[x].ls].sum+t[t[x].rs].sum; 35 return; 36 } 37 ll Query(int x,ll k){ 38 if(k==0)return 0; 39 if(k>=t[x].cnt)return t[x].sum; 40 int l=t[x].l,r=t[x].r,ls=t[x].ls,rs=t[x].rs; 41 if(l==r)return (k*belong[l]); 42 if(t[ls].cnt>=k)return Query(ls,k); 43 else return (t[ls].sum+Query(rs,k-t[ls].cnt)); 44 } 45 int main(){ 46 scanf("%d%d",&M,&N); 47 for(int i=1;i<=M;i++)scanf("%d%d%d",&a[i].s,&a[i].e,&a[i].p),a[i].e++; 48 sort(a+1,a+M+1,cmp1); 49 for(int i=1;i<=M;i++) 50 if(a[i].p!=a[i-1].p)belong[a[i].hp=++cnt_p]=a[i].p;else a[i].hp=cnt_p; 51 for(int i=1;i<=M;i++){ 52 b[++num_b].data=a[i].s;b[num_b].o=1;b[num_b].p=a[i].hp; 53 b[++num_b].data=a[i].e;b[num_b].o=2;b[num_b].p=a[i].hp; 54 } 55 Build(root[0]=++num_treenode,1,cnt_p); 56 sort(b+1,b+num_b+1,cmp2); 57 for(int i=1;i<=num_b;i++){ 58 int v=b[i].data,o=b[i].o,p=b[i].p; 59 Update(root[i-1],root[i]=++num_treenode,p,o); 60 if(v!=b[i+1].data)belong_root[v]=i; 61 } 62 for(int i=1;i<=N;i++)if(belong_root[i]==0)belong_root[i]=belong_root[i-1]; 63 while(N--){ 64 scanf("%d%d%d%d",&X,&A,&B,&C); 65 K=1+(Pre*A+B)%C; 66 Pre=Query(root[belong_root[X]],K); 67 printf("%lld\n",Pre); 68 } 69 return 0; 70 }

By:AlenaNuna

主席樹||可持久化線段樹||離散化||[CQOI2015]任務查詢系統||BZOJ 3932||Luogu P3168