HDU - 4747 Mex

HDU-4747

题意:对于每一段连续区间找到mex的值(mex 即为没出现过的数的最小非负数),然后对所有的改值进行求和, 输出ans。

题解:首先我门可以暴力的跑出 区间 [1,2], [1,3],……,[1,i]的mex值, 由于mex的定义, 我们可以得知, 左边的区间mex一定是不大于右边的区间的mex值, 然后可以通过线段树求和, 来访问这些值的和。 然后查询完一次数据之后, 我们将删除第一个数, 并且判断在[l+1,r-1](l为被删数出现的位置, r为下一个该数出现的位置) 的区间内是否有mex值大于该删除的值, 如果有就更新这一段区间的值, 用线段树加速更新操作,最后删完所有的点所统计的和就是答案了。

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
  4 #define LL long long
  5 #define ULL unsigned LL
  6 #define fi first
  7 #define se second
  8 #define pb push_back
  9 #define lson l,m,rt<<1
 10 #define rson m+1,r,rt<<1|1
 11 #define max3(a,b,c) max(a,max(b,c))
 12 #define min3(a,b,c) min(a,min(b,c))
 13 typedef pair<int,int> pll;
 14 const int INF = 0x3f3f3f3f;
 15 const LL mod = 1e9+7;
 16 const int N = 2e5+10;
 17 LL Max[N<<2], sum[N<<2], lazy[N<<2];
 18 int a[N], mex[N];
 19 void PushUp(int rt){
 20     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
 21     Max[rt] = max(Max[rt<<1|1], Max[rt<<1]);
 22 }
 23 void PushDown(int rt, int llen, int rlen){
 24     if(lazy[rt] != -1){
 25         lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
 26         sum[rt<<1] = lazy[rt]*llen;
 27         sum[rt<<1|1] = lazy[rt]*rlen;
 28         Max[rt<<1] = Max[rt<<1|1] = lazy[rt];
 29         lazy[rt] = -1;
 30     }
 31 }
 32 void Build(int l, int r, int rt){
 33     lazy[rt] = -1;
 34     if(l == r) {
 35         Max[rt] = sum[rt] = mex[l];
 36         return ;
 37     }
 38     int m = l+r >> 1;
 39     Build(lson);
 40     Build(rson);
 41     PushUp(rt);
 42 }
 43 void Update(int l, int r, int rt, int L, int R, int c){
 44     if(L <= l && r <= R){
 45         Max[rt] = lazy[rt] = c;
 46         sum[rt] = 1ll * (r-l+1) * c;
 47         return ;
 48     }
 49     int m = l+r >> 1;
 50     PushDown(rt, m-l+1, r-m);
 51     if(L <= m) Update(lson, L, R, c);
 52     if(m < R) Update(rson, L, R, c);
 53     PushUp(rt);
 54 }
 55 LL Query(int l, int r, int rt, int L, int R){
 56     if(L <= l && r <= R)  return sum[rt];
 57     int m = l+r >> 1;
 58     LL ret = 0;
 59     PushDown(rt, m-l+1, r-m);
 60     if(L <= m) ret += Query(lson, L, R);
 61     if(m < R)  ret += Query(rson, L, R);
 62     return ret;
 63 }
 64 int id(int l, int r, int rt, int v){
 65     if(l == r) return l;
 66     int m = l+r >> 1;
 67     PushDown(rt, m-l+1, r-m);
 68     if(Max[rt<<1] > v) return id(lson, v);
 69     return id(rson, v);
 70 }
 71 map<int, int> mp;
 72 int Next[N];
 73 int main(){
 74     ///Fopen;
 75     int n;
 76     while(~scanf("%d", &n), n){
 77         for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
 78         mp.clear();
 79         int tmp = 0;
 80         for(int i = 1; i <= n; i++){
 81             mp[a[i]] = 1;
 82             while(mp.count(tmp)) tmp++;
 83             mex[i] = tmp;
 84         }
 85 
 86         mp.clear();
 87         for(int i = n; i >= 1; i--){
 88             if(!mp.count(a[i])) Next[i] = n + 1;
 89             else Next[i] = mp[a[i]];
 90             mp[a[i]] = i;
 91         }
 92         Build(1,n,1);
 93         LL ans = 0;
 94         for(int i = 1; i <= n; i++){
 95             ans += sum[1];
 96             if(Max[1] > a[i]){
 97                 int l = id(1,n,1,a[i]);//找到最左边的大于被删除数的位置,由mex的定义可知,后面的值一定也不小于这个节点
 98                 int r = Next[i];
 99                 if(l < r) Update(1, n, 1, l, r-1, a[i]);
100             }
101             Update(1,n,1,i,i,0);
102         }
103         printf("%I64d\n", ans);
104     }
105     return 0;
106 }
HDU 4747

猜你喜欢

转载自www.cnblogs.com/MingSD/p/9098220.html
Mex