BZOJ 3339 Rmq Problem(离线+线段树+mex函数)
题意:
q次询问,问[l,r]子区间的mex值
思路:
对子区间[l,r],当l固定的时候,[l,r]的mex值对r单调不减
对询问按照l离线,对当前的l,都有维护一个线段树,每个叶节点保存[l,r]的mex
l每增大1,都要更新[l, next[l]-1],将这个区间内大于a[l]的值更新为a[l]
其中next[i]为i之后的下一个a[i]位置
代码:
线段树写的不熟。。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 //#define lowbit(x) ((x)&(-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 1e9+7; const int maxn = 2e6+100; const int maxm = 2e6+100; const int inf = 0x3f3f3f3f; const db pi = acos(-1.0); int a[maxn]; int n, q; int nx[maxn]; int lst[maxn]; struct node{ int l, r; int id; }b[maxn]; bool cmp(node a, node b){ return a.l<b.l; } int mex[maxn]; set<int>s; int dat[maxn]; void build(int l, int r, int root){ int mid = (l+r)>>1; if(l==r){ dat[root] = mex[l]; return; } dat[root] = inf; build(lson); build(rson); return; } void pushdown(int l, int r, int root){ if(l==r)return; dat[lc]=min(dat[lc],dat[root]); dat[rc]=min(dat[rc],dat[root]); return; } int ask(int x, int l, int r, int root){ if(dat[root]!=inf)pushdown(l, r, root); if(l==r)return dat[root]; int mid = (l+r)>>1; if(x<=mid)return ask(x,lson); return ask(x,rson); } void update(int x, int y, int val, int l, int r, int root){ if(dat[root]!=inf)pushdown(l,r,root); if(l==x&&y==r){ dat[root]=min(dat[root],val);return; } int mid = (l+r)>>1; if(y<=mid)update(x,y,val,lson); else if(x>mid)update(x,y,val,rson); else{ update(x,mid,val,lson); update(mid+1,y,val,rson); } return; } int ans[maxn]; int main(){ scanf("%d %d", &n, &q); for(int i = 1; i <= n; i++){ nx[i]=n+1; } for(int i = 1; i <= n; i++){ scanf("%d", &a[i]); if(lst[a[i]]){ nx[lst[a[i]]]=i; } lst[a[i]]=i; } int tmp = 0; for(int i = 1; i <= n; i++){ s.insert(a[i]); while(s.find(tmp)!=s.end()){ tmp++; } mex[i]=tmp; }build(1,n,1); for(int i = 1; i <= q; i++){b[i].id=i; scanf("%d %d", &b[i].l, &b[i].r); } sort(b+1,b+1+q,cmp); int p = 1; for(int i = 1; i <= q; i++){ while(p<b[i].l){ //printf("\\\\%d\n",p); update(p,nx[p]-1,a[p],1,n,1); //printf("---\n"); p++; } //printf("==%d %d %d\n",b[i].id,b[i].l,b[i].r); //printf("--%d %d\n",i,ask(b[i].r,1,n,1)); ans[b[i].id]=ask(b[i].r,1,n,1); } for(int i = 1; i <= q; i++){ printf("%d\n",ans[i]); } return 0; } /* 7 5 0 2 1 0 1 3 2 1 3 2 3 1 4 3 6 2 7 */