AlenaNuna

导航

主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex

题面:Rmq Problem / mex

题解:

先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空白叫做A[i-1].data+1,

开头和最尾也要这么插,意义是如果取不了A[i-1]了,最早能取的是啥数。要把这些空白也离散化然后扔主席树里啊。

主席树维护每个数A[i]出现的最晚位置(tree[i].data),查询时查询root[R]的树中最早的data<L的节点(这意味着该节点的下标离散化前代

表的数没有在区间L到R中)。

顺带一提,这道题也可以用莫队套分块做,原理十分好理解,分块维护的是权值,块[i]维护该块是否被填满。我也扔了代码。

另外,我主席树的空间开的其实是不对的,但是bzoj空间比较卡,所以开小点理论上是不对的,但是数据没有那么极端而已。

代码:

主席树||可持久化线段树+离散化版:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #define max(a,b) ((a)>(b)?(a):(b))
 6 #define min(a,b) ((a)<(b)?(a):(b))
 7 using namespace std;
 8 inline int rd(){
 9     int x=0,f=1;char c=getchar();
10     while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
11     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
12     return f*x;
13 }
14 const int maxn=200000+50,maxm=200000+50,inf=1<<30;
15 int N,M,cor[maxn<<1],lsh_cnt=0,root[maxn<<1],num_treenode=0,L,R;
16 bool pb[maxn<<1];
17 struct _A{int id,yn,data;}A[maxn];
18 inline bool cmp(const _A&a,const _A&b){return a.yn<b.yn;}
19 struct Tree{
20     int l,r,data,ls,rs;
21 }t[maxn*25];
22 inline void Build(int x,int l,int r){
23     t[x].l=l;t[x].r=r;int mid=(l+r)>>1;
24     if(l==r){
25         if(pb[l])t[x].data=0;
26         return;
27     }
28     Build(t[x].ls=++num_treenode,l,mid);
29     Build(t[x].rs=++num_treenode,mid+1,r);
30     return;
31 }
32 inline void Update(int u,int x,int q,int s){
33     int l=t[u].l,r=t[u].r,mid=(l+r)>>1,ls=t[u].ls,rs=t[u].rs;
34     t[x].l=l;t[x].r=r;
35     if(l==r&&l==q){t[x].data=s; return;}
36     if(q<=mid){t[x].rs=rs; Update(ls,t[x].ls=++num_treenode,q,s);}
37           else{t[x].ls=ls; Update(rs,t[x].rs=++num_treenode,q,s);}
38     ls=t[x].ls;rs=t[x].rs;
39     t[x].data=min(t[ls].data,t[rs].data);
40     return;
41 }
42 inline int Query(int x,int s){
43     int l=t[x].l,r=t[x].r,ls=t[x].ls,rs=t[x].rs;
44     if(l==r)return l;
45     if(t[ls].data<s)return Query(ls,s);else return Query(rs,s);
46 }
47 inline bool cmp2(const _A&a,const _A&b){return a.id<b.id;}
48 int main(){
49     N=rd();M=rd();
50     for(int i=1;i<=N;i++){A[i].yn=rd();A[i].id=i;}
51     sort(A+1,A+N+1,cmp);
52     if(A[1].yn!=0){
53         cor[++lsh_cnt]=0;
54         pb[lsh_cnt]=1;
55     }
56     A[1].data=++lsh_cnt;
57     cor[lsh_cnt]=A[1].yn;
58     for(int i=2;i<=N;i++)
59         if(A[i].yn!=A[i-1].yn){
60             if(A[i].yn!=A[i-1].yn+1){
61                 cor[++lsh_cnt]=A[i-1].yn+1;
62                 pb[lsh_cnt]=1;
63             }
64             A[i].data=++lsh_cnt;
65             cor[lsh_cnt]=A[i].yn;
66         }
67         else A[i].data=lsh_cnt;
68     cor[++lsh_cnt]=A[N].yn+1;
69     pb[lsh_cnt]=1;
70     Build(root[0]=++num_treenode,1,lsh_cnt);
71     sort(A+1,A+N+1,cmp2);
72     for(int i=1;i<=N;i++)
73         Update(root[i-1],root[i]=++num_treenode,A[i].data,A[i].id);
74     while(M--){
75         L=rd();R=rd();
76         printf("%d\n",cor[Query(root[R],L)]);
77     }
78     return 0;
79 }

 

莫队套分块版:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 inline int rd(){
 8     int f=1,x=0;char c=getchar();
 9     while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
10     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
11     return f*x;
12 }
13 const int maxn=200005,maxm=200005,max_block=500;
14 int N,M,A[maxn],l,r,block,Ans[maxm],vis[maxn],cnt[max_block],num,belong[maxn];
15 struct Q{
16     int id,l,r;
17 }q[maxm];
18 inline bool cmp(const Q&a,const Q&b){
19     if(belong[a.l]==belong[b.l])return a.r<b.r;
20     return a.l<b.l;
21 }
22 inline void Add(int x){
23     if(x<=N){
24         if(vis[x]==0)cnt[belong[x]]++;
25         vis[x]++;
26     }
27     return;
28 }
29 inline void Del(int x){
30     if(x<=N){
31         vis[x]--;
32         if(vis[x]==0)cnt[belong[x]]--;
33     }
34     return;
35 }
36 int main(){
37     N=rd();M=rd();
38     block=sqrt(N);
39     num=N/block;
40     if(N%block)num++;
41     for(int i=1;i<=N;i++){
42         A[i]=rd();
43         belong[i]=(i-1)/block+1;
44     }
45     belong[0]=0;
46     for(int i=1;i<=M;i++){
47         q[i].id=i;
48         q[i].l=rd();
49         q[i].r=rd();
50     }
51     sort(q+1,q+M+1,cmp);
52     l=1;r=0;
53     for(int i=1;i<=M;i++){
54         int ql=q[i].l,qr=q[i].r,id=q[i].id;
55         while(l<ql)Del(A[l++]);
56         while(l>ql)Add(A[--l]);
57         while(r<qr)Add(A[++r]);
58         while(r>qr)Del(A[r--]);
59         if(cnt[0]==0){
60             Ans[id]=0;
61             continue;
62         }
63         int t=-1;
64         for(int j=1;j<=num;j++){
65             if(j!=num&&cnt[j]!=block){
66                 t=j;
67                 break;
68             }
69             else if(cnt[j]!=N-(num-1)*block) t=j;
70         }
71         if(t==-1){
72             Ans[id]=N;
73             continue;
74         }
75         int f=(t-1)*block+1,toj=t*block;
76         for(int j=f;j<=toj;j++)
77             if(vis[j]==0){
78                 Ans[id]=j;
79                 break;
80             }    
81     }
82     for(int i=1;i<=M;i++)printf("%d\n",Ans[i]);
83     return 0;
84 }

By:AlenaNuna

posted on 2019-02-27 22:08  AlenaNuna  阅读(155)  评论(0编辑  收藏  举报