zoukankan      html  css  js  c++  java
  • hdu 4747 Mex

    http://acm.hdu.edu.cn/showproblem.php?pid=4747

    题意:定义一个函数mex(i,j),mex(i,j)为从i到j之间没有出现的最小的非负整数,求所有的mex(i,j)的值的和。

    我们可以知道mex(i,i+1)到mex(i,i+n)的值是递增的。可以先求从mex(1,1),mex(1,2)....mex(1,n)的值,然后通过以1开始的mex推出以2开始的mex的值,以此递推下去。

    使用线段树维护,删除前面的数。删掉第一个数a[1]. 那么在下一个a[1]出现前的 大于a[1]的mex值都要变成a[1]。使用线段树维护区间的值修改和区间求和。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <map>
      4 #include <algorithm>
      5 #define LL long long
      6 #define maxn 200001
      7 using namespace std;
      8 
      9 LL max2(LL a,LL b)
     10 {
     11     return b>a?b:a;
     12 }
     13 
     14 struct node
     15 {
     16     int l,r;
     17     int max1;
     18     LL sum;
     19     int flag;
     20 } tree[maxn*4];
     21 int a[maxn];
     22 int n;
     23 int mex[maxn];
     24 int next[maxn];
     25 
     26 void build(int i,int l,int r)
     27 {
     28     tree[i].l=l;
     29     tree[i].r=r;
     30     tree[i].flag=0;
     31     if(l==r)
     32     {
     33         tree[i].max1=mex[l];
     34         tree[i].sum=mex[l];
     35         return ;
     36     }
     37     int mid=(l+r)>>1;
     38     build(i<<1,l,mid);
     39     build(i<<1|1,mid+1,r);
     40     tree[i].max1=max2(tree[i<<1].max1,tree[i<<1|1].max1);
     41     tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
     42 }
     43 
     44 
     45 void down(int i)
     46 {
     47     if(tree[i].l==tree[i].r) return ;
     48     if(tree[i].flag)
     49     {
     50         tree[i<<1].sum=(LL)tree[i].max1*(tree[i<<1].r-tree[i<<1].l+1);
     51         tree[i<<1].max1=tree[i].max1;
     52         tree[i<<1].flag=1;
     53         tree[i<<1|1].sum=(LL)tree[i].max1*(tree[i<<1|1].r-tree[i<<1|1].l+1);
     54         tree[i<<1|1].max1=tree[i].max1;
     55         tree[i<<1|1].flag=1;
     56         tree[i].flag=0;
     57     }
     58 }
     59 
     60 void update(int i,int l,int r,int key)
     61 {
     62     if(tree[i].l==l&&tree[i].r==r)
     63     {
     64         tree[i].sum=(LL)key*(tree[i].r-tree[i].l+1);
     65         tree[i].max1=key;
     66         tree[i].flag=1;
     67         return;
     68     }
     69     down(i);
     70     int mid=(tree[i].l+tree[i].r)>>1;
     71     if(r<=mid)
     72     {
     73         update(i<<1,l,r,key);
     74     }
     75     else if(l>mid)
     76     {
     77         update(i<<1|1,l,r,key);
     78     }
     79     else
     80     {
     81         update(i<<1,l,mid,key);
     82         update(i<<1|1,mid+1,r,key);
     83     }
     84     if(tree[i].l!=tree[i].r)
     85     {
     86         tree[i].max1=max2(tree[i<<1].max1,tree[i<<1|1].max1);
     87         tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
     88    }
     89 }
     90 
     91 int get_max(int i,int key)
     92 {
     93     if(tree[i].l==tree[i].r)
     94     {
     95         return tree[i].l;
     96     }
     97     down(i);
     98     if(tree[i<<1].max1>key)
     99      return get_max(i<<1,key);
    100     else  return get_max(i<<1|1,key);
    101 }
    102 int main()
    103 {
    104     while(scanf("%d",&n)!=EOF)
    105     {
    106         if(n==0) break;
    107         for(int i=1; i<=n; i++)
    108         {
    109             scanf("%d",&a[i]);
    110         }
    111         map<int,int>q;
    112         int t1=0;
    113         for(int i=1; i<=n; i++)
    114         {
    115             q[a[i]]=1;
    116             while(q.find(t1)!=q.end()) t1++;
    117             mex[i]=t1;
    118         }
    119         q.clear();
    120         for(int i=n; i>=1; i--)
    121         {
    122             if(q.find(a[i])==q.end()) next[i]=n+1;
    123             else next[i]=q[a[i]];
    124             q[a[i]]=i;
    125         }
    126         build(1,1,n);
    127         LL ans=0;
    128         for(int i=1; i<=n; i++)
    129         {
    130             ans+=tree[1].sum;
    131             if(tree[1].max1>a[i])
    132             {
    133                 int ll=get_max(1,a[i]);
    134                 int rr=next[i];
    135                 if(ll<rr)
    136                 {
    137                     update(1,ll,rr-1,a[i]);
    138                 }
    139             }
    140             update(1,i,i,0);
    141         }
    142         printf("%I64d
    ",ans);
    143     }
    144     return 0;
    145 }
    View Code
  • 相关阅读:
    AtCoder,Codeforces做题记录
    最小割分治(最小割树):BZOJ2229 && BZOJ4519
    [BZOJ2209][JSOI2011]括号序列(splay)
    [BZOJ5461][LOJ#2537[PKUWC2018]Minimax(概率DP+线段树合并)
    [LOJ#2540][PKUWC2018]随机算法(概率DP)
    [CC-SEABUB]Sereja and Bubble Sort
    [CC-ANUGCD]Maximum number, GCD condition
    [HDU5965]扫雷
    [ZJOI2007]最大半连通子图
    [BZOJ2152]聪聪可可
  • 原文地址:https://www.cnblogs.com/fanminghui/p/3904160.html
Copyright © 2011-2022 走看看