• 省队集训 Day4 a


    【题目大意】

    求有多少区间只包含1个出现次数为1的数。

    $1leq n leq 5*10^5, 0 leq a_i leq 10^9$

    【题解】

    考虑枚举右端点,设这个数上一次出现位置为pre[i],那么就是$[pre[i]+1,i]$区间加1,$[pre[pre[i]]+1, pre[i]]$区间减1,和统计区间中1的个数。

    注意到数不会减到负的,那么1只可能是最小值或次小值,那么线段树直接维护即可。

    复杂度$O(nlogn)$。

    考场交错代码导致爆0...QAQ

    # include <vector>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long double ld;
    
    const int M = 5e5 + 10, N = 1e5 + 10, inf = 1e9;
    
    inline int getint() {
        int x = 0; char ch = getchar();
        while(!isdigit(ch)) ch = getchar();
        while(isdigit(ch)) x = (x<<3) + (x<<1) + ch - '0', ch = getchar();
        return x;
    }
    
    int n, m, a[M], pre[M], lst[M];
    vector<int> ps;
    
    struct pa {
        int x, tx, y, ty;
        pa() {}
        pa(int x, int tx, int y, int ty) : x(x), tx(tx), y(y), ty(ty) {}
        inline friend pa operator + (pa a, pa b) {
            pa c;
            if(a.x < b.x) {
                c.x = a.x, c.tx = a.tx;
                c.y = min(a.y, b.x); c.ty = 0;
                if(a.y == c.y) c.ty += a.ty;
                if(b.x == c.y) c.ty += b.tx;
            } else if(a.x > b.x) {
                c.x = b.x, c.tx = b.tx;
                c.y = min(a.x, b.y); c.ty = 0;
                if(a.x == c.y) c.ty += a.tx;
                if(b.y == c.y) c.ty += b.ty;
            } else {
                c.x = a.x, c.tx = a.tx + b.tx;
                c.y = min(a.y, b.y); c.ty = 0;
                if(a.y == c.y) c.ty += a.ty;
                if(c.y == b.y) c.ty += b.ty;
            }
            return c;
        }
    };
    
    struct SMT {
        pa w[M << 2]; int tag[M << 2];    
        # define ls (x<<1)
        # define rs (x<<1|1) 
        inline void up(int x) {
            w[x] = w[ls] + w[rs];
        }
        
        inline void pushtag(int x, int t) {
            w[x].x += t;
            if(w[x].y != inf) w[x].y += t;
            tag[x] += t;
        }
        
        inline void down(int x) {
            if(!tag[x]) return ;
            pushtag(ls, tag[x]);
            pushtag(rs, tag[x]);
            tag[x] = 0;
        }
        
        inline void build(int x, int l, int r) {
            if(l == r) {
                w[x].x = 0, w[x].tx = 1;
                w[x].y = inf, w[x].ty = 0;
                return ;
            }
            int mid = l+r >> 1;
            build(ls, l, mid);
            build(rs, mid+1, r);
            up(x);
        }    
        
        inline void edt(int x, int l, int r, int L, int R, int d) {
            if(L <= l && r <= R) {
                pushtag(x, d);
                return ;
            }
            down(x);
            int mid = l+r>>1;
            if(L <= mid) edt(ls, l, mid, L, R, d);
            if(R > mid) edt(rs, mid+1, r, L, R, d);
            up(x);
        }
        
        inline pa sum(int x, int l, int r, int L, int R) {
            if(L <= l && r <= R) return w[x];
            down(x);
            int mid = l+r>>1;
            if(R <= mid) return sum(ls, l, mid, L, R);
            else if(L > mid) return sum(rs, mid+1, r, L, R);
            else return sum(ls, l, mid, L, mid) + sum(rs, mid+1, r, mid+1, R);
        }    
        
        inline void debug(int x, int l, int r) {
            printf("x = %d,l = %d,r = %d,mi = %d,semi = %d,minum = %d,seminum = %d,tag = %d
    ", x, l, r, w[x].x, w[x].y, w[x].tx, w[x].ty, tag[x]);
            if(l == r) return ;
            int mid = l+r>>1;
            debug(ls, l, mid); debug(rs, mid+1, r);
        }
    }T;
         
    
    int main() {
        freopen("a1.in", "r", stdin);
    //    freopen("a.out", "w", stdout);
        n = getint();
        for (int i=1; i<=n; ++i) {
            a[i] = getint();
            ps.push_back(a[i]);
        }
        sort(ps.begin(), ps.end());
        ps.erase(unique(ps.begin(), ps.end()), ps.end()); 
        m = ps.size();
        for (int i=1; i<=n; ++i) a[i] = lower_bound(ps.begin(), ps.end(), a[i]) - ps.begin() + 1;
        for (int i=1; i<=n; ++i) pre[i] = lst[a[i]], lst[a[i]] = i;
        ll ans = 0; pa t; T.build(1, 1, n);
        for (int i=1; i<=n; ++i) {
    //        T.debug(1, 1, n); cout << endl;
            T.edt(1, 1, n, pre[i] + 1, i, 1);
            if(pre[i]) T.edt(1, 1, n, pre[pre[i]] + 1, pre[i], -1);
            t = T.sum(1, 1, n, 1, i);
            if(t.x == 1) ans += t.tx;
            if(t.y == 1) ans += t.ty;
            // 区间加1,区间减1,查询区间内1的出现次数
        }
        cout << ans;    
        return 0;
    }
    View Code
  • 相关阅读:
    AtCoder Grand Contest 015 C
    AtCoder Grand Contest 011 F
    AtCoder Regular Contest 076 E
    AtCoder Grand Contest 016 B
    AtCoder Grand Contest 010 F
    AtCoder Regular Contest 081 F
    AtCoder Grand Contest 018 D
    AtCoder Regular Contest 076 F
    yii2.0 如何按需加载并管理CSS样式及JS脚本
    ebay商品基本属性组合成数据表格式,可用上传到系统递交数据
  • 原文地址:https://www.cnblogs.com/galaxies/p/20170710_a.html
Copyright © 2020-2023  润新知