• HDU 4747 Mex


    Mex

    Time Limit: 5000ms
    Memory Limit: 65535KB
    This problem will be judged on HDU. Original ID: 4747
    64-bit integer IO format: %I64d      Java class name: Main
     
    Mex is a function on a set of integers, which is universally used for impartial game theorem. For a non-negative integer set S, mex(S) is defined as the least non-negative integer which is not appeared in S. Now our problem is about mex function on a sequence.

    Consider a sequence of non-negative integers {ai}, we define mex(L,R) as the least non-negative integer which is not appeared in the continuous subsequence from aL to aR, inclusive. Now we want to calculate the sum of mex(L,R) for all 1 <= L <= R <= n.
     

    Input

    The input contains at most 20 test cases.
    For each test case, the first line contains one integer n, denoting the length of sequence.
    The next line contains n non-integers separated by space, denoting the sequence.
    (1 <= n <= 200000, 0 <= ai <= 10^9)
    The input ends with n = 0.
     

    Output

    For each test case, output one line containing a integer denoting the answer.
     

    Sample Input

    3
    0 1 3
    5
    1 0 2 0 1
    0

    Sample Output

    5
    24

    Hint

    For the first test case: mex(1,1)=1, mex(1,2)=2, mex(1,3)=2, mex(2,2)=0, mex(2,3)=0,mex(3,3)=0. 1 + 2 + 2 + 0 +0 +0 = 5.
     

    Source

     
    解题:这题好难啊。。。参考自Oyking
     
    那么从0开始考虑,如果只有一个0,出现在了x位置,那么s[1,x-1]的子段的mex值都为0,所以$S[i] = n-x+1(i < x)$,大于 x 的 s[i]都为0(大于x的子段不存在0,他们的最小非负数都为0)
    如果有两个0,那么设第一个0位置为x,第二个0位置为y,那么$s[i] = n-x+1(i < x),s[i] = n - y + 1(x≤i<y)$,大于 y 的 s[i]都为0
    有多个0也一样,处理完0之后,得到的sum{s[i]}就是最少为1的mex子段数
    然后从1开始往上处理,对某一个数在位置x,$s[i] = min(n-x+1, s[i])$
    每处理完一个数,就得到一个sum{s[i]} ,依次可以得到最少为2的mex字段数,最少为3的mex字段数……把这些都加起来就是答案。
     
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int maxn = 200010;
     5 struct arc {
     6     int pos,next;
     7     arc(int x = 0,int y = -1) {
     8         pos = x;
     9         next = y;
    10     }
    11 } e[maxn<<2];
    12 struct node {
    13     LL sum;
    14     int lazy,minv,maxv;
    15 } tree[maxn<<2];
    16 int head[maxn],a[maxn],tot,n;
    17 void add(int u,int pos) {
    18     e[tot] = arc(pos,head[u]);
    19     head[u] = tot++;
    20 }
    21 inline void pushup(int v) {
    22     tree[v].minv = min(tree[v<<1].minv,tree[v<<1|1].minv);
    23     tree[v].maxv = max(tree[v<<1].maxv,tree[v<<1|1].maxv);
    24     tree[v].sum = tree[v<<1].sum + tree[v<<1|1].sum;
    25 }
    26 inline void pushdown(int L,int R,int v) {
    27     if(tree[v].lazy != -1) {
    28         int mid = (L + R)>>1;
    29         tree[v<<1].maxv = tree[v<<1].minv = tree[v].lazy;
    30         tree[v<<1].sum = (LL)tree[v].lazy*(mid - L + 1);
    31         tree[v<<1].lazy = tree[v].lazy;
    32         tree[v<<1|1].maxv = tree[v<<1|1].minv = tree[v].lazy;
    33         tree[v<<1|1].lazy = tree[v].lazy;
    34         tree[v<<1|1].sum = (LL)tree[v].lazy*(R - mid);
    35         tree[v].lazy = -1;
    36     }
    37 }
    38 void build(int lt,int rt,int v) {
    39     tree[v].lazy = -1;
    40     if(lt == rt) {
    41         tree[v].maxv = tree[v].minv = tree[v].sum = n - lt + 1;
    42         return;
    43     }
    44     int mid = (lt + rt)>>1;
    45     build(lt,mid,v<<1);
    46     build(mid+1,rt,v<<1|1);
    47     pushup(v);
    48 }
    49 void update(int L,int R,int lt,int rt,int val,int v) {
    50     if(tree[v].maxv <= val) return;
    51     if(lt <= L && rt >= R && tree[v].minv >= val) {
    52         tree[v].maxv = tree[v].minv = val;
    53         tree[v].sum = LL(val)*(R - L + 1);
    54         tree[v].lazy = val;
    55         return;
    56     }
    57     pushdown(L,R,v);
    58     int mid = (L + R)>>1;
    59     if(lt <= mid) update(L,mid,lt,rt,val,v<<1);
    60     if(rt > mid) update(mid+1,R,lt,rt,val,v<<1|1);
    61     pushup(v);
    62 }
    63 int main() {
    64     while(scanf("%d",&n),n) {
    65         memset(head,-1,sizeof head);
    66         tot = 0;
    67         for(int i = 1; i <= n; ++i) scanf("%d",a+i);
    68         for(int i = n; i > 0; --i) if(a[i] <= n) add(a[i],i);
    69         build(1,n,1);
    70         LL ret = 0;
    71         for(int i = 0; i <= n && tree[1].sum; ++i){
    72             int last = 0;
    73             for(int j = head[i]; ~j; j = e[j].next){
    74                 update(1,n,last+1,e[j].pos, n - e[j].pos + 1,1);
    75                 last = e[j].pos;
    76             }
    77             if(last < n) update(1,n,last + 1,n,0,1);
    78             ret += tree[1].sum;
    79         }
    80         printf("%I64d
    ",ret);
    81     }
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    myeclipse 8.6 安装svn插件
    最简单的jdbc程序
    win7 安装Redis
    面试问题
    在linux/unix中查找大文件
    Java:单例模式的七种写法
    JAVA设计模式之单例模式
    java_String和StringBuffer区别分析
    stringbuffer与stringbuilder的区别?
    String与StringBuffer的区别
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4787167.html
Copyright © 2020-2023  润新知