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

    题意:有一个序列a[],mex(L, R)表示区间a在区间[L, R]上第一个没出现的最小非负整数,对于序列a[],求所有的mex(L, R)的和(1 <= L <= R <= n,1 <= n <= 200000,0 <= ai <= 10^9)。

    求出所有的mex(1, i);接着删去第1个结点,就是所有的mex(2, i);接着再删去第1个结点,就是所有的mex(3, i);……最后就是mex(n, n),求和即是答案。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <cmath>
      6 
      7 using namespace std;
      8 #define ls rt<<1
      9 #define rs rt<<1|1
     10 #define lson l, m, rt<<1
     11 #define rson m + 1, r, rt<<1|1
     12 typedef long long ll;
     13 const int maxn = 2e5 + 5;
     14 int n, a[maxn], vis[maxn], next[maxn], mex1[maxn << 2];
     15 struct SegTree{
     16     int Max, lazy;
     17     ll sum;
     18 }seg[maxn << 2];
     19 
     20 void pushUp(int rt){
     21     seg[rt].sum = seg[ls].sum + seg[rs].sum;
     22     seg[rt].Max = max(seg[ls].Max, seg[rs].Max);
     23 }
     24 void pushDown(int rt, int len){
     25     if (seg[rt].lazy != -1){
     26         seg[ls].lazy = seg[rs].lazy = seg[rt].lazy;
     27         seg[ls].Max = seg[rt].lazy;
     28         seg[rs].Max = seg[rt].lazy;
     29         seg[ls].sum = (ll)((len + 1) / 2) * ((ll)seg[rt].lazy);
     30         seg[rs].sum = (ll)(len / 2) * ((ll)seg[rt].lazy);
     31         seg[rt].lazy = -1;
     32     }
     33 }
     34 void build(int l, int r, int rt){
     35     seg[rt].lazy = -1;
     36     if (l == r){
     37         seg[rt].sum = seg[rt].Max = mex1[l];
     38         return ;
     39     }
     40     int m = (l + r) >> 1;
     41     build(lson);
     42     build(rson);
     43     pushUp(rt);
     44 }
     45 int find(int key, int l, int r, int rt){//找到第一个mex大于a[i]的下标
     46     if (l == r) return l;
     47     pushDown(rt, r - l + 1);
     48     int m = (l + r) >> 1;
     49     if (seg[ls].Max > key) return find(key, lson);
     50     else return find(key, rson);
     51 }
     52 void update(int val, int L, int R, int l, int r, int rt){
     53     if (L <= l && r <= R){
     54         //pushDown(rt, r - l + 1);
     55         seg[rt].Max = val;
     56         seg[rt].sum = (ll) val * (ll) (r - l + 1);
     57         seg[rt].lazy = val;
     58         return ;
     59     }
     60     int m = (l + r) >> 1;
     61     //cout << seg[rt].lazy << " l = " << l << " r= " << r << endl;
     62     pushDown(rt, r - l + 1);
     63     if (L <= m ) update(val, L, R, lson);
     64     if (R > m) update(val, L, R, rson);
     65     pushUp(rt);
     66     /*if (L == 2 && R == 4){
     67         cout << " ll = " << l << " rr = " << r << endl;
     68         cout << " sum = " << seg[rt].sum << " rt = " << rt << endl;
     69     }*/
     70 }
     71 int main(){
     72     while (~scanf("%d", &n) && n){
     73         for (int i = 1; i <= n; ++i){
     74             scanf("%d", &a[i]);
     75             if (a[i] > n) a[i] = n;
     76         }
     77         //得到mex[1, i]
     78         int tmp = 0;
     79         memset(vis, 0, sizeof(vis));
     80         for (int i = 1; i <= n; ++i){
     81             vis[a[i]] = 1;
     82             while(vis[tmp]) tmp++;
     83             mex1[i] = tmp;
     84         }
     85         //得到next值
     86         for (int i = 0; i <= n; ++i) vis[i] = n + 1;
     87         for (int i = n; i >= 1; --i){
     88             next[i] = vis[a[i]];
     89             vis[a[i]] = i;
     90         }
     91         build(1, n, 1);
     92         ll ans = 0;
     93         for (int i = 1; i <= n; ++i){
     94         //    cout << seg[1].sum << endl;
     95             ans += seg[1].sum;
     96             update(0, i, i, 1, n, 1);
     97             if (a[i] < seg[1].Max){
     98                 int l = find(a[i], 1, n, 1), r = next[i] - 1;
     99                 //cout << " l = " << l << " r = " << r << endl;
    100                 if (l <= r) update(a[i], l, r, 1, n, 1);
    101             }
    102         }
    103         printf("%I64d
    ", ans);
    104     }
    105     return 0;
    106 }
  • 相关阅读:
    尽管以C++为基础,但 Java 是一种更纯粹的面向对象程序设计语言
    Java 还是 C++?
    计划的回报
    阶段4:校订
    阶段3:开始创建
    阶段2:如何构建?
    阶段1:要制作什么?
    阶段0:拟出一个计划
    不要迷失
    分析和设计
  • 原文地址:https://www.cnblogs.com/Missa/p/3361432.html
Copyright © 2011-2022 走看看