hdu 4747 Mex

参考这篇文章:http://www.shuizilong.com/house/archives/hdu-4747-mex/


#include <iostream>
#include <vector>
#include <stack>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>

using namespace std;

/*  define */
#define sf(a) scanf("%d",&a)
#define sf3(a,b,c) scanf("%d%d%d",&(a),&(b),&(c))
#define sfs(a) scanf("%s",a)
#define clr(a) memset(a,0,sizeof(a))
#define pfI(a) printf("%I64d\n",a)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define rep1(i,a,b) for(int i=(a);i<(b);i++)
#define repd(i,a,b) for(int i=(a);i>=(b);i--)
/*  define */

/*    segment tree   */
#define root 1,1,n
#define now o,l,r
#define m (l+r)/2
#define lson o*2,l,m
#define rson o*2+1,m+1,r
/*    segment tree   */

/*     num theory    */
int gcd(int a,int b){
    return b==0?a:gcd(b,a%b);
}
/*     num theory    */

typedef long long ll;

const int inf = (1<<29);
const int N = 210000;

int mx[N*4],hash[N],mex1[N];
int c,lazy[N*4],st,ed;
ll ss[N*4];
/*
    pushup
    tansfer the information from
    the children to his father
*/
void Up(int o){
    mx[o]=max(mx[o*2],mx[o*2+1]);
    ss[o]=ss[o*2]+ss[o*2+1];
}

/*
    when it is cover a segment
    do this operation
*/
void Op_Cov(int o,int l,int r,int val){
    mx[o]=val;ss[o]=(ll)(r-l+1)*val;lazy[o]=1;
}

/*
    to release the lazy flag
    and tansfer the lazy flag to his children
*/
void release(int o,int l,int r){
    if(lazy[o]){
        Op_Cov(lson,mx[o]);Op_Cov(rson,mx[o]);
        lazy[o]=0;
    }
}

/*
    just upper_bound
    cause it is monotonic
*/
int Upper_bound(int o,int l,int r){
    if(l==r) return l;
    release(now);
    if(mx[o*2]>c)
        return Upper_bound(lson);
    else
        return Upper_bound(rson);
}

/*
    build a segment tree
    and reset the lazy flag
*/
void build(int o,int l,int r){
    lazy[o]=0;if(l==r){
        mx[o]=ss[o]=mex1[l];
        return ;
    }
    build(lson);build(rson);
    Up(o);
}

/*
   reset the segment [st,ed]
*/
void Update(int o,int l,int r){
    if(l>=st && r<=ed){
        Op_Cov(now,c);
        return ;
    }
    release(now);
    if(st<=m) Update(lson);
    if(m<ed) Update(rson);
    Up(o);
}

int A[N],nxt[N];
int main(){
    int n;
    while(~sf(n) && n){
        rep(i,1,n){
            sf(A[i]);A[i]=A[i]>200001?200001:A[i];
        }
        int mex=0;
        clr(hash);
        rep(i,1,n){
            hash[A[i]]=1;
            while(hash[mex]) mex++;
            mex1[i]=mex;
        }
        fill(hash,hash+N,n+1);
        repd(i,n,1){
            nxt[i]=hash[A[i]];
            hash[A[i]]=i;
        }
        build(root);
        ll ans=0;
        rep(i,1,n){
            ans+=ss[1];if(mx[1]>A[i]){
                c=A[i];st=Upper_bound(root);ed=nxt[i]-1;
                if(st<=ed) Update(root);
            }
            st=i,ed=i,c=0;Update(root);
            if(!mx[1]) break;
        }
        pfI(ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值