HDU 4747 线段树 区间更新

来源:互联网 发布:男士内裤淘宝店铺名 编辑:程序博客网 时间:2024/06/08 11:10

线段树 区间更新

题意:

给出一个数列,现在定义一个function,数列的某一个区间

[i,j]
里从0开始没有出现的最小值就是f(i,j) 的值。

现在请求出该数列所有子区间的函数值。

思路:

首先太菜,看题,看数据、看意思、分析函数,但是也没有看出这是一个可以用线段树解决的问题。比较菜。分析数据200000的数据量,其子区间会很多,暴力解决必定超时,而在分析函数,每次如果只求出

[1,i],[1,i+1],[1,n][2,i],[2,i+1],[2,n]
也就是每次删除最开始的一个数,然后求出区间和的话,只需更新函数的值即可 。f函数值是递增的,可以手动分析一下,如果删除最前面的一个数字比如删除了a[1] ,那么受影响的是f(1,i) > a[i] 而a[i] 的下一次出现的位置便不受影响。所以区间更新即可。

#include <iostream>#include <cstdio>#include <cstring>#include <map>using namespace std;const int maxn = 200005;int n,a[maxn],Next[maxn],mex[maxn];map<int,int>mp;struct Node{    int l,r;    long long sum;    int mx;    int lazy;}rt[maxn*3];void Update_same(int i,int v)   /*lazy的妙用*/{    rt[i].sum = (long long)v*(rt[i].r - rt[i].l + 1);    rt[i].mx = v;    rt[i].lazy = true;}void Push_up(int i)     /*向上更新mx和sum*/{    if(rt[i].l == rt[i].r ) return ;    rt[i].sum = rt[i<<1].sum + rt[(i<<1)|1].sum;    rt[i].mx = max(rt[i<<1].mx,rt[(i<<1)|1].mx);}void push_down(int i)   /*向下更新,lazy的使用可以减少很多不必要的运算*/{    if(rt[i].l == rt[i].r ) return ;    if(rt[i].lazy) {        Update_same(i<<1,rt[i].mx);        Update_same((i<<1)|1,rt[i].mx);        rt[i].lazy = 0;    }}void build(int i,int l,int r)   /*建树*/{    rt[i].l = l;    rt[i].r = r;    rt[i].lazy = 0;    if(l == r) {        rt[i].sum = mex[l];        rt[i].mx = mex[l];        return ;    }    int mid = (l + r) >> 1;    build(i<<1,l,mid);    build((i<<1)|1,mid+1,r);    Push_up(i);}void Update(int i,int l,int r,int v)    /*区间更新,可以当模板*/{    if(rt[i].l == l && rt[i].r == r) {        Update_same(i,v);        return ;    }    push_down(i);    int mid = (rt[i].l + rt[i].r)>>1;    if(mid >= r)        Update(i<<1,l,r,v);    else if(l > mid) {        Update((i<<1)|1,l,r,v);    }    else {        Update(i<<1,l,mid,v);        Update((i<<1)|1,mid+1,r,v);    }    Push_up(i);}int Get(int i,int v)    /*返回mx > v 的区间位置*/{    if(rt[i].l == rt[i].r) return rt[i].l;    push_down(i);    if(rt[i<<1].mx > v)        return Get(i<<1,v);    else         return Get((i<<1)|1,v);}int main(int argc, char const *argv[]){    //freopen("in.txt","r",stdin);    while(scanf("%d",&n) != EOF && n) {        for(int i = 1;i <= n; i++)             scanf("%d",&a[i]);        mp.clear();        int temp = 0;        for(int i = 1;i <= n; i++) {            mp[a[i]] = 1;            while(mp.find(temp) != mp.end()) temp++;            mex[i] = temp;        }        mp.clear();        for(int i = n;i >= 1; i--) {            if(mp.find(a[i]) == mp.end()) Next[i] = n + 1;            else Next[i] = mp[a[i]];            mp[a[i]] = i;        }        build(1,1,n);        long long ans = 0;        for(int i = 1;i <= n; i++) {            ans += rt[1].sum;            if(rt[1].mx > a[i]) {                int l = Get(1,a[i]);                int r = Next[i];                if(r > l) {                    Update(1,l,r-1,a[i]);                }            }            Update(1,i,i,0);        }        printf("%I64d\n",ans);    }    return 0;}
原创粉丝点击