Ji driver line segment tree 2 questions

On 51nod , I worshipped the live broadcast of Jidriver's line segment tree, and wrote two questions, namely hdu5306 and bzoj4355 . Because the coding ability is too rubbish, I wrote each question for two days.
The main idea is to use cut to prune the update of the line segment tree, and use check to control the conditions of violent update. Probably the interval coverage or similar operations will make the interval more and more the same. For the operation of making the interval the same (potential energy reduction?), it can be updated violently, and the operation without reducing the potential energy can basically be marked.

The whole framework is as follows:

void update(int u, int ql, int qr, int c, int l, int r){
    if(r<ql||qr<l||cut())return;
    if(ql<=l&&r<=qr&&check()){
        putlazy(u,c);
        return;
    }
    int mid=(l+r)/2;
    pushdown(u);
    update(2*u, ql, qr, c, l, mid);
    update(2*u+1, ql, qr, c, mid+1, r);
    pushup(u);
}

For the question of hdu5306, considering the operation of taking min between interval and t, there are the following situations:
case 1: t is greater than the maximum value, and the interval remains unchanged at this time;
case 2: t is less than the strict second largest value, at least the maximum value is used at this time. The value becomes the same as the next largest value, even if the interval becomes the same, violent update is allowed;
case 3: t is greater than the strict second largest value, and less than the maximum value, here can be marked as lazy.

Considering the query, you only need to maintain the maximum value, the maximum number, and the strict second largest value.

//吉司机宇宙线段树之王!
#include <bits/stdc++.h>
using namespace std;
const int maxn=1000005;
typedef long long ll;

int mx[maxn<<2];
int cnt[maxn<<2];
int se[maxn<<2];
int lazy[maxn<<2];
ll sum[maxn<<2];
int a[maxn];
int n, m;

void putlazy(int u, int t){
    sum[u]-=1LL*cnt[u]*(mx[u]-t);
    mx[u]=t;
    lazy[u]=t;
}

void pushdown(int u){
    if(lazy[u]==-1)return;
    if(mx[2*u]>lazy[u]){
        sum[2*u]-=1LL*cnt[2*u]*(mx[2*u]-lazy[u]);
        mx[2*u]=lazy[u];
        lazy[2*u]=lazy[u];
    }
    if(mx[2*u+1]>lazy[u]){
        sum[2*u+1]-=1LL*cnt[2*u+1]*(mx[2*u+1]-lazy[u]);
        mx[2*u+1]=lazy[u];
        lazy[2*u+1]=lazy[u];

    }
    lazy[u]=-1;
}

void pushup(int u){
    if(mx[2*u]==mx[2*u+1]){
        mx[u]=mx[2*u];
        cnt[u]=cnt[2*u]+cnt[2*u+1];
        se[u]=max(se[2*u], se[2*u+1]);
        sum[u]=sum[2*u]+sum[2*u+1];
    }
    else if(mx[2*u]>mx[2*u+1]){
        mx[u]=mx[2*u];
        cnt[u]=cnt[2*u];
        se[u]=max(se[2*u], mx[2*u+1]);
        sum[u]=sum[2*u]+sum[2*u+1];
    }
    else {
        mx[u]=mx[2*u+1];
        cnt[u]=cnt[2*u+1];
        se[u]=max(mx[2*u], se[2*u+1]);
        sum[u]=sum[2*u]+sum[2*u+1];
    }
}

void build(int u, int l, int r){
    lazy[u]=-1;
    if(l==r){
        mx[u]=sum[u]=a[l];
        cnt[u]=1;
        se[u]=-1;
        return;
    }
    int mid=l+r>>1;
    build(2*u, l, mid);
    build(2*u+1, mid+1, r);
    pushup(u);
}

void update(int u, int ql, int qr, int t, int l, int r){
    if(ql>r||qr<l||mx[u]<=t)return;
    if(ql<=l&&r<=qr&&se[u]<t){
        putlazy(u, t);
        return;
    }
    pushdown(u);
    int mid=l+r>>1;
    update(2*u, ql, qr, t, l, mid);
    update(2*u+1, ql, qr, t, mid+1, r);
    pushup(u);
}

int getmx(int u, int ql, int qr, int l, int r){
    if(ql>r||qr<l)return 0;
    if(ql<=l&&r<=qr)return mx[u];
    pushdown(u);
    int mid=l+r>>1;
    int ans=0;
    ans=max(ans, getmx(2*u, ql, qr, l, mid));
    ans=max(ans, getmx(2*u+1, ql, qr, mid+1, r));
    return ans;
}

ll getsum(int u, int ql, int qr, int l, int r){
    if(ql>r||qr<l)return 0;
    if(ql<=l&&r<=qr)return sum[u];
    pushdown(u);
    int mid=l+r>>1;
    ll ans=0;
    ans+=getsum(2*u, ql, qr, l, mid);
    ans+=getsum(2*u+1, ql, qr, mid+1, r);
    return ans;
}

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &m);
        for(int i=1;i<=n;i++)scanf("%d", &a[i]);
        build(1, 1, n);
        for(int i=1;i<=m;i++){
            int tag;
            scanf("%d", &tag);
            if(tag==0){
                int x, y, t;
                scanf("%d%d%d", &x, &y, &t);
                update(1, x, y, t, 1, n);
            }
            else if(tag==1){
                int x, y;
                scanf("%d%d", &x, &y);
                printf("%d\n", getmx(1, x, y, 1, n));
            }
            else {
                int x, y;
                scanf("%d%d", &x, &y);
                printf("%lld\n", getsum(1, x, y, 1, n));
            }
        }
    }
}

And for bzoj4355, it's basically similar. It is necessary to maintain the minimum value of the interval, the number of minimum values ​​in the interval, and the strict sub-minimum value.
For operation 1 interval assignment, if the interval is different, it must be the same interval, so it can be updated violently, and when the interval is all the same, the interval assignment can be regarded as an interval increase, and the interval increase can be marked.
For operation 2, it can be regarded as the first interval increase, and then the interval and 0 take the max.
Similar to the operation in the previous question, the only difference is to maintain two lazy marks, one is the interval increase, and the other is the interval taking max.

//吉司机线段树
//牛逼啊
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=300005;

int n, m;
ll mn[maxn<<2];
int cnt[maxn<<2];
ll se[maxn<<2];
ll lzcut[maxn<<2];
ll lzadd[maxn<<2];
int a[maxn];

void putcut(int u, ll c){
    mn[u]=c;
    lzcut[u]=c;
}

void putadd(int u, ll c){
    lzadd[u]+=c;
    if(lzcut[u]!=-1)lzcut[u]+=c;
    mn[u]+=c;
    if(se[u]!=-1)se[u]+=c;
}

void pushdown(int u){
    if(lzadd[u]){
        putadd(2*u, lzadd[u]);
        putadd(2*u+1, lzadd[u]);
        lzadd[u]=0;
    }
    if(lzcut[u]!=-1){
        if(mn[2*u]<lzcut[u]){
            mn[2*u]=lzcut[u];
            lzcut[2*u]=lzcut[u];
        }
        if(mn[2*u+1]<lzcut[u]){
            mn[2*u+1]=lzcut[u];
            lzcut[2*u+1]=lzcut[u];
        }
        lzcut[u]=-1;
    }
}

void pushup(int u){
    if(mn[2*u]==mn[2*u+1]){
        mn[u]=mn[2*u];
        cnt[u]=cnt[2*u]+cnt[2*u+1];
        if(se[2*u]==-1&&se[2*u+1]==-1)se[u]=-1;
        else if(se[2*u]==-1)se[u]=se[2*u+1];
        else if(se[2*u+1]==-1)se[u]=se[2*u];
        else se[u]=min(se[2*u], se[2*u+1]);
    }
    else if(mn[2*u]<mn[2*u+1]){
        mn[u]=mn[2*u];
        cnt[u]=cnt[2*u];
        if(se[2*u]==-1){
            se[u]=mn[2*u+1];
        }
        else {
            se[u]=min(mn[2*u+1], se[2*u]);
        }
    }
    else {
        mn[u]=mn[2*u+1];
        cnt[u]=cnt[2*u+1];
        if(se[2*u+1]==-1){
            se[u]=mn[2*u];
        }
        else {
            se[u]=min(mn[2*u], se[2*u+1]);
        }
    }
}

void build(int u, int l, int r){
    lzcut[u]=-1;
    lzadd[u]=0;
    if(l==r){
        mn[u]=a[l];
        cnt[u]=1;
        se[u]=-1;
        return;
    }
    int mid=(l+r)/2;
    build(2*u, l, mid);
    build(2*u+1, mid+1, r);
    pushup(u);
}

void cover(int u, int ql, int qr, int c, int l, int r){
    if(r<ql||qr<l)return;
    if(ql<=l&&r<=qr&&se[u]==-1){
        putadd(u, (ll)c-mn[u]);
        return;
    }
    int mid=(l+r)/2;
    pushdown(u);
    cover(2*u, ql, qr, c, l, mid);
    cover(2*u+1, ql, qr, c, mid+1, r);
    pushup(u);
}

void add(int u, int ql, int qr, int c, int l, int r){
    if(r<ql||qr<l||(se[u]==-1&&mn[u]==0&&c<=0))return;
    if(ql<=l&&r<=qr){
        if(mn[u]+c>=0){
            putadd(u, c);
            return;
        }
        else if(se[u]==-1||se[u]+c>0){
            putadd(u, c);
            putcut(u, 0);
            return;
        }
    }
    int mid=(l+r)/2;
    pushdown(u);
    add(2*u, ql, qr, c, l, mid);
    add(2*u+1, ql, qr, c, mid+1, r);
    pushup(u);
}

int query(int u, int ql, int qr, int l, int r){
    if(r<ql||qr<l)return 0;
    if(ql<=l&&r<=qr){
        if(mn[u]==0)return cnt[u];
        return 0;
    }
    int mid=(l+r)/2;
    int ret=0;
    pushdown(u);
    ret+=query(2*u, ql, qr, l, mid);
    ret+=query(2*u+1, ql, qr, mid+1, r);
    return ret;
}


int main(){
    scanf("%d%d", &n, &m);
    for(int i=1;i<=n;i++){
        scanf("%d", &a[i]);
    }
    build(1, 1, n);
    for(int i=1;i<=m;i++){
        int tag;
        scanf("%d", &tag);
        if(tag==1){
            int l, r, c;
            scanf("%d%d%d", &l, &r, &c);
            cover(1, l, r, c, 1, n);
        }
        else if(tag==2){
            int l, r, c;
            scanf("%d%d%d", &l, &r, &c);
            add(1, l, r, c, 1, n);
        }
        else {
            int l, r;
            scanf("%d%d", &l, &r);
            printf("%d\n", query(1, l, r, 1, n));
        }
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325946008&siteId=291194637