zoukankan      html  css  js  c++  java
  • HDU 4747 Mex (2013杭州网络赛1010题,线段树)

    Mex

    Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
    Total Submission(s): 623    Accepted Submission(s): 209


    Problem Description
    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
     
    Recommend
    liuyiding
     

    题目定义了mex(i,j)表示,没有在i到j之间出现的最小的非负整数。

    求所有组合的i,j(i<=j)的和

    就是求mex(1,1) + mex(1,2)+....+mex(1,n)

    +mex(2,2) + mex(2,3) + ...mex(2,n)

    +mex(3,3) + mex(3,4)+...+mex(3,n)

    + mex(n,n)

    可以知道mex(i,i),mex(i,i+1)到mex(i,n)是递增的。

    首先很容易求得mex(1,1),mex(1,2)......mex(1,n)

    因为上述n个数是递增的。

    然后使用线段树维护,需要不断删除前面的数。

    比如删掉第一个数a[1]. 那么在下一个a[1]出现前的 大于a[1]的mex值都要变成a[1]

    因为是单调递增的,所以找到第一个 mex > a[1]的位置,到下一个a[1]出现位置,这个区间的值变成a[1].

    然后需要线段树实现区间修改和区间求和。

      1 /* ***********************************************
      2 Author        :kuangbin
      3 Created Time  :2013-9-17 21:15:02
      4 File Name     :G:2013ACM练习2013网络赛2013杭州网络赛1010.cpp
      5 ************************************************ */
      6 
      7 #pragma comment(linker, "/STACK:1024000000,1024000000")
      8 #include <stdio.h>
      9 #include <string.h>
     10 #include <iostream>
     11 #include <algorithm>
     12 #include <vector>
     13 #include <queue>
     14 #include <set>
     15 #include <map>
     16 #include <string>
     17 #include <math.h>
     18 #include <stdlib.h>
     19 #include <time.h>
     20 using namespace std;
     21 
     22 const int MAXN = 200010;
     23 struct Node
     24 {
     25     int l,r;
     26     long long sum;//区间和
     27     int mx;//最大值
     28     int lazy;//懒惰标记,表示赋值为相同的
     29 }segTree[MAXN*3];
     30 void push_up(int i)
     31 {
     32     if(segTree[i].l == segTree[i].r)return;
     33     segTree[i].sum = segTree[i<<1].sum + segTree[(i<<1)|1].sum;
     34     segTree[i].mx = max(segTree[i<<1].mx,segTree[(i<<1)|1].mx);
     35 }
     36 void Update_Same(int i,int v)
     37 {
     38     segTree[i].sum = (long long)v*(segTree[i].r - segTree[i].l + 1);
     39     segTree[i].mx = v;
     40     segTree[i].lazy = 1;
     41 }
     42 void push_down(int i)
     43 {
     44     if(segTree[i].l == segTree[i].r)return;
     45     if(segTree[i].lazy)
     46     {
     47         Update_Same(i<<1,segTree[i].mx);
     48         Update_Same((i<<1)|1,segTree[i].mx);
     49         segTree[i].lazy = 0;
     50     }
     51 }
     52 int mex[MAXN];
     53 void Build(int i,int l,int r)
     54 {
     55     segTree[i].l = l;
     56     segTree[i].r = r;
     57     segTree[i].lazy = 0;
     58     if(l == r)
     59     {
     60         segTree[i].mx = mex[l];
     61         segTree[i].sum = mex[l];
     62         return;
     63     }
     64     int mid = (l + r)>>1;
     65     Build(i<<1,l,mid);
     66     Build((i<<1)|1,mid+1,r);
     67     push_up(i);
     68 }
     69 //将区间[l,r]的数都修改为v
     70 void Update(int i,int l,int r,int v)
     71 {
     72     if(segTree[i].l == l && segTree[i].r == r)
     73     {
     74         Update_Same(i,v);
     75         return;
     76     }
     77     push_down(i);
     78     int mid = (segTree[i].l + segTree[i].r)>>1;
     79     if(r <= mid)
     80     {
     81         Update(i<<1,l,r,v);
     82     }
     83     else if(l > mid)
     84     {
     85         Update((i<<1)|1,l,r,v);
     86     }
     87     else
     88     {
     89         Update(i<<1,l,mid,v);
     90         Update((i<<1)|1,mid+1,r,v);
     91     }
     92     push_up(i);
     93 }
     94 //得到值>= v的最左边位置
     95 int Get(int i,int v)
     96 {
     97     if(segTree[i].l == segTree[i].r)
     98         return segTree[i].l;
     99     push_down(i);
    100     if(segTree[i<<1].mx > v)
    101         return Get(i<<1,v);
    102     else return Get((i<<1)|1,v);
    103 }
    104 int a[MAXN];
    105 map<int,int>mp;
    106 int next[MAXN];
    107 int main()
    108 {
    109     //freopen("in.txt","r",stdin);
    110     //freopen("out.txt","w",stdout);
    111     int n;
    112     while(scanf("%d",&n) && n)
    113     {
    114         for(int i = 1;i <= n;i++)
    115             scanf("%d",&a[i]);
    116         mp.clear();
    117         int tmp = 0;
    118         for(int i = 1;i <= n;i++)
    119         {
    120             mp[a[i]] = 1;
    121             while(mp.find(tmp) != mp.end())tmp++;
    122             mex[i] = tmp;
    123         }
    124         mp.clear();
    125         for(int i = n;i >= 1;i--)
    126         {
    127             if(mp.find(a[i]) == mp.end())next[i] = n+1;
    128             else next[i] = mp[a[i]];
    129             mp[a[i]] = i;
    130         }
    131         Build(1,1,n);
    132         long long sum = 0;
    133         for(int i = 1;i <= n;i++)
    134         {
    135             sum += segTree[1].sum;
    136             if(segTree[1].mx > a[i])
    137             {
    138                 int l = Get(1,a[i]);
    139                 int r = next[i];
    140                 if(l < r)
    141                     Update(1,l,r-1,a[i]);
    142             }
    143             Update(1,i,i,0);
    144         }
    145         printf("%I64d
    ",sum);
    146 
    147     }
    148     return 0;
    149 }
  • 相关阅读:
    关于Maya Viewport 2.0 API 开发的介绍视频
    春节大假
    Some tips about the life cycle of Maya thread pool
    Can I compile and run Dx11Shader for Maya 2015 on my side?
    How to get current deformed vertex positions in MoBu?
    想加入全球首届的 欧特克云加速计划吗?
    三本毕业(非科班),四次阿里巴巴面试,终拿 offer(大厂面经)
    mac、window版编辑器 webstorm 2016... 永久破解方法。
    node 搭载本地代理,处理web本地开发跨域问题
    js 一维数组,转成嵌套数组
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3327674.html
Copyright © 2011-2022 走看看