zoukankan      html  css  js  c++  java
  • HDU 4747 Mex (线段树)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

    题目:给出一个序列,mex{}表示集合中没有出现的最小的自然数。然后 求sigma(mex (i , j)).

    比赛的时候,被老大秒了。。。太可怕了。。。

    做法:考虑左端点固定时的所有区间的mex值,这个序列是一个非递减了。。。首先要明白。

    初始就是求出mex[i]表示 mex(1 , i),对于每一个左端点,就是一个区间求和。

    现在需要考虑的是左端点的改变对于序列的影响。。。

    即左端点从i -> i + 1,mex[j]的改变。。。。即删去ai对于序列的影响。

    如果 a[j] = a[i] 且 j > i ,不存在a[k] = a[i]  j > k > i。即a[i]下一次出现的位置 。

    根据mex的定义,我们知道 mex[k]不会改变, k >= j。因为删掉的ai还是存在于序列当中,所以不受影响。

    之后需要考虑的是i +1 到 j - 1这段区间的mex值。。。删去了ai之后,使得原先mex值大于ai的,都会更新成ai。

    很好理解。。。因为是没有出现的最小的,ai更小。。。

    之前说过这是一个非递减的序列,所以原先mex值大于ai的也是一段连续的区间,所以我们可以找到最靠左的位置 r,使得mex[r] > a[i]。那么r 到 j - 1这段区间的mex值便 会更新为a[i]。

    所以全部搞定。。。用线段树维护一下mex序列,区间更新,区间求和,然后一个查找就可以了。。。

    下面的代码是我把老大的code中线段树部分重写后的。。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <bitset>
    #include <algorithm>
    #include <functional>
    #include <numeric>
    #include <utility>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <string>
    #include <cstring>
    using namespace std;
    
    typedef unsigned int UI;
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef vector<bool> VB;
    typedef vector<char> VC;
    typedef vector<double> VD;
    typedef vector<string> VS;
    typedef vector<VI> VVI;
    typedef vector<PII> VPII;
    
    template <class T> inline void checkMin(T& a, T b) { if (b < a) a = b; }
    template <class T> inline void checkMax(T& a, T b) { if (b > a) a = b; }
    
    const int MOD = 1000000007;
    const int dx[] = {0, -1, 0, 1};
    const int dy[] = {1, 0, -1, 0};
    
    bool cmp(const PII& a, const PII& b) {
        if (a.first != b.first) return a.first < b.first;
        else return a.second < b.second;
    }
    
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    const int N = 200010;
    
    PII b[N];
    int n, m, a[N], vis[N], next[N];
    
    #define lson step << 1
    #define rson step << 1 | 1
    
    struct Node {
        int left , right;
        int mx , lazy;
        LL sum; 
    }L[N << 2];
    void pushUp (int step) {
        L[step].sum = L[lson].sum + L[rson].sum;
        L[step].mx = max (L[lson].mx , L[rson].mx);
    }
    void update (int step , int l , int r , int w) ;
    void pushDown (int step) {
        int l = L[step].left , r = L[step].right , m = (l + r) >> 1;
        int &z = L[step].lazy;
        if (z != -1) {
            update (lson , l , m , z);
            update (rson , m + 1 ,r , z);
            z = -1;
        }
    }
    void bulid (int step , int l , int r) {
        L[step].left = l;
        L[step].right = r;
        L[step].mx =  L[step].sum = 0;
        L[step].lazy = -1;
        if (l == r) return ;
        int m = (l + r) >> 1;
        bulid (lson , l , m);
        bulid (rson , m + 1 , r);
    }
    void update (int step , int p , int w) {
        if (L[step].left == L[step].right) {
            L[step].mx = L[step].sum = w;
            return ;
        }
        pushDown (step);
        int m = (L[step].left + L[step].right) >> 1;
        if (p <= m) update (lson , p , w);
        else update (rson , p , w);
        pushUp (step);
    }
    void update (int step , int l , int r , int w) {
        if (L[step].left == l && L[step].right == r) {
            L[step].lazy = w;
            L[step].mx = w;
            L[step].sum = (r - l + 1) * 1LL * w;
            return ;
        }
        pushDown (step);
        int m = (L[step].left + L[step].right) >> 1;
        if (r <= m) update (lson , l , r , w);
        else if (l > m) update (rson , l , r , w);
        else {
            update (lson , l , m , w);
            update (rson , m + 1 , r , w);
        }
        pushUp (step);
    }
    int queryp (int step , int w) {
        if (L[step].mx <= w) return n + 1;
        if (L[step].left == L[step].right) return L[step].left;
        pushDown (step);
        int m = (L[step].left + L[step].right) >> 1;
        if (L[lson].mx > w) return queryp (lson , w);
        else return queryp (rson , w);
    
    }
    LL querys (int step , int l , int r) {
        if (L[step].left == l && L[step].right == r) 
            return L[step].sum ;
        pushDown (step);
        int m = (L[step].left + L[step].right) >> 1;
        if (r <= m) return querys (lson , l , r);
        else if (l > m) return querys (rson , l , r);
        else return querys (lson , l , m) + querys (rson , m + 1 , r);
    }
    
    int main() {
        #ifndef ONLINE_JUDGE
            freopen ("input.txt" , "r" , stdin);
            // freopen ("output.txt" , "w" , stdout);
        #endif
        while (scanf("%d", &n) != EOF && n != 0) {
            for (int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
                b[i] = make_pair(a[i], i);
                next[i] = n + 1;
                vis[i] = false;
            } 
            vis[0] = false;
            sort(b + 1, b + n + 1, cmp); 
            b[n + 1].first = b[n].first, b[n + 1].second = n + 1;
            for (int i = 1; i <= n; i++) {
                if (b[i + 1].first == b[i].first) next[b[i].second] = b[i + 1].second;
            }
            bulid (1 , 1 , n);
            int mmex = 0;
            for (int i = 1; i <= n; i++) {
                if (a[i] <= n) vis[a[i]] = true;
                while (vis[mmex]) mmex++;
                update(1 , i, mmex);
            }
            LL ans = 0;
            a[0] = n + 1; next[0] = n + 1;
            for (int l = 1; l <= n; l++) {
                if (a[l - 1] <= mmex) {
                    int p0 = queryp(1 ,a[l - 1]);
                    if (p0 != -1) 
                        p0 = max (p0, l);
                    int p1 = next[l - 1];
                    if (p0 >= l && p0 < p1) 
                        update(1 ,p0 , p1 - 1 , a[l - 1]);
                }
                ans += querys(1 , l, n);
            }
            printf("%I64d
    ", ans);
        }
        return 0



  • 相关阅读:
    topcoder srm 495 div1
    topcoder srm 500 div1
    topcoder srm 485 div1
    topcoder srm 490 div1
    IDEWorkspaceChecks.plist文件是干什么用的?
    博客推荐
    如何使用U盘安装macOS high Sierra?
    小程序--模板消息调研
    小程序--剖析小程序上传文件
    小程序--小程序开发过程中遇到的问题以及解决方案
  • 原文地址:https://www.cnblogs.com/pangblog/p/3327657.html
Copyright © 2011-2022 走看看