主席树||可持久化线段树||离散化||[CQOI2015]任务查询系统||BZOJ 3932||Luogu P3168
题目: [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