AlenaNuna

导航

主席树||可持久化线段树||离散化||[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

posted on 2019-02-21 21:53  AlenaNuna  阅读(145)  评论(0编辑  收藏  举报