zoukankan      html  css  js  c++  java
  • HUAS 1483 mex(离线+线段树)

    实在是太弱了。。。。

    考虑离线,从mex[l,r]向mex[l,r+1]转移,显然是没啥东西可以记录的。。。

    从mex[l,r]向mex[l+1,r]转移,记x=mex[l,r],如果[l+1,r]不出现a[l]的话,那么mex[l+1,r]=min(mex[l,r],a[l]).

    有了这个性质的话,就可以考虑离线了。先预处理一遍to[]和mex[],to[i]表示i的后面下一个出现a[i]的数组下标,mex[i]表示mex[1,i]。

    把询问按左端点升序排序,对于当前的左端点为1的排序,可以直接输出它的mex值。

    当左端点向右移一位的时候,mex[2,j]=min(mex[1,j],a[1]).(j<to[1]).

    如果暴力修改的话还是会超时的。

    很幸运mex数组是单调非递减的。那么我们可以用线段树把区间[2,j]上的值取个min。用tag思想的话很容易做到logn。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi 3.1415926535
    # define eps 1e-9
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=200005;
    //Code begin...
    
    struct Node{int l, r, id;}node[N];
    int seg[N<<2], a[N], mex[N], vis[N], to[N], now, tag[N<<2], ans[N], res;
    
    bool comp(Node a, Node b){return a.l<b.l;}
    void init(int p, int l, int r){
        if (l<r) {
            int mid=(l+r)>>1;
            init(lch); init(rch); return ;
        }
        seg[p]=mex[l];
    }
    void push_down(int p, int l, int r){
        if (tag[p]==-1) return ;
        if (l==r) seg[p]=min(seg[p],tag[p]);
        else {
            tag[p<<1]=(tag[p<<1]==-1?tag[p]:min(tag[p],tag[p<<1]));
            tag[p<<1|1]=(tag[p<<1|1]==-1?tag[p]:min(tag[p],tag[p<<1|1]));
        }
        tag[p]=-1;
    }
    void update(int p, int l, int r, int L, int R, int val){
        if (L>r||R<l) return ;
        push_down(p,l,r);
        if (L<=l&&R>=r) tag[p]=val;
        else {
            int mid=(l+r)>>1;
            update(lch,L,R,val); update(rch,L,R,val);
        }
    }
    void query(int p, int l, int r, int L){
        if (L>r||L<l) return ;
        push_down(p,l,r);
        if (L==r&&L==l) res=seg[p];
        else {
            int mid=(l+r)>>1;
            query(lch,L); query(rch,L);
        }
    }
    int main ()
    {
        int n, q;
        mem(tag,-1);
        n=Scan(); q=Scan();
        FOR(i,1,n) {
            a[i]=Scan();
            if (vis[a[i]]) to[vis[a[i]]]=i;
            vis[a[i]]=i;
            while (vis[now]) ++now;
            mex[i]=now;
        }
        FOR(i,1,n) if (!to[i]) to[i]=n+1;
        FOR(i,1,q) node[i].l=Scan(), node[i].r=Scan(), node[i].id=i;
        sort(node+1,node+q+1,comp);
        now=1;
        init(1,1,n);
        FOR(i,1,q) {
            while (now!=node[i].l) {
                if (now+1<=to[now]-1) update(1,1,n,now+1,to[now]-1,a[now]);
                ++now;
            }
            query(1,1,n,node[i].r);
            ans[node[i].id]=res;
        }
        FOR(i,1,q) printf("%d
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    2021年4月28日
    2021年4月18日
    2021年3月4日
    2020年11月20日
    20201112
    ThreadLocal原理分析
    git与gitlab
    DevOps与CICD简介
    代码扫描利器sonarqube
    看完小白也会使用,Android投屏神器scrcpy详细教程
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6624611.html
Copyright © 2011-2022 走看看