BZOJ3339 Rmq Problem

【bzoj3339】Rmq Problem

Description

Input

Output

Sample Input

7 5 0 2 1 0 1 3 2 1 3 2 3 1 4 3 6 2 7

Sample Output

3 0 3 2 4

HINT

orz hzwer学长

转-----------------------------------

这一题在线似乎比较麻烦,至于离线。

首先按照左端点将询问排序

然后一般可以这样考虑

首先如何得到1-i的sg值呢

这个可以一开始扫一遍完成

接着考虑l-r和l+1-r的答案有何不同

显然是l-next[l]-1这一段所有sg值大于a[l]的变为a[l]

这一步如果暴力修改的话只有30分

但是修改区间我们可以想到线段树,这样就能a了

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=200010;
const int inf=1e9;
int n,m,A[maxn],mark[maxn],val[maxn],next[maxn],last[maxn],ans[maxn],minv[maxn*3];
struct Query
{
    int id,l,r;
    bool operator < (const Query& ths) const {return l<ths.l;}
}q[maxn];
void build(int o,int l,int r)
{
    if(l==r) minv[o]=val[l];
    else
    {
        int mid=l+r>>1,lc=o<<1,rc=lc|1;
        build(lc,l,mid);build(rc,mid+1,r);
        minv[o]=inf;
    }
}
void pushdown(int o)
{
    int lc=o<<1,rc=lc|1;
    minv[lc]=min(minv[o],minv[lc]);
    minv[rc]=min(minv[o],minv[rc]);    
}
int query(int o,int l,int r,int pos)
{
    if(l!=r&&minv[o]!=inf) pushdown(o);
    if(l==r) return minv[o];
    int mid=l+r>>1,lc=o<<1,rc=lc|1;
    if(pos<=mid) return query(lc,l,mid,pos);
    return query(rc,mid+1,r,pos);
}
void update(int o,int l,int r,int ql,int qr,int v)
{
    if(l!=r&&minv[o]!=inf) pushdown(o);
    if(ql<=l&&r<=qr) minv[o]=min(minv[o],v);
    else
    {
        int mid=l+r>>1,lc=o<<1,rc=lc|1;
        if(ql<=mid) update(lc,l,mid,ql,qr,v);
        if(qr>mid) update(rc,mid+1,r,ql,qr,v);
    }
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++) A[i]=read();
    for(int i=1;i<=n;i++)
    {
        mark[A[i]]=1;
        for(int j=val[i-1];;j++) if(!mark[j]) {val[i]=j;break;}
    }
    for(int i=n;i;i--) next[i]=last[A[i]]?last[A[i]]:n+1,last[A[i]]=i;
    build(1,1,n);
    for(int i=1;i<=m;i++) q[q[i].id=i].l=read(),q[i].r=read();
    sort(q+1,q+m+1);
    int cur=1;
    for(int i=1;i<=m;i++)
    {
        while(cur<q[i].l)
        {
            update(1,1,n,cur,next[cur]-1,A[cur]);
            cur++;
        }
        ans[q[i].id]=query(1,1,n,q[i].r);
    }
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}
View Code

 

posted @ 2015-06-03 12:28  wzj_is_a_juruo  阅读(203)  评论(0编辑  收藏  举报