1. 程式人生 > >BZOJ4364:[IOI2014]Wall

BZOJ4364:[IOI2014]Wall

淺談區間最值操作與歷史最值問題:https://www.cnblogs.com/AKMer/p/10225100.html

題目傳送門:https://lydsy.com/JudgeOnline/problem.php?id=4364

似乎可以不用吉司機線段樹的作法……因為只需要維護區間最大最小值,也只有區間取最大最小值操作,所以可以直接用普通的線段樹延遲標記解決這道問題。只要把最大值標記和最小值標記之間的關係處理得當即可。

時間複雜度:\(O((n+m)logn)\)

空間複雜度:\(O(n)\)

程式碼如下:

#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=2e6+6,inf=1e9;

int n,m;

int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

struct segmemt_tree {
    int mx[maxn<<2],mn[maxn<<2];
    int tagmx[maxn<<2],tagmn[maxn<<2];

    void update(int p) {
        mx[p]=max(mx[p<<1],mx[p<<1|1]);
        mn[p]=min(mn[p<<1],mn[p<<1|1]);
    }

    void build(int p,int l,int r) {
        tagmx[p]=-inf,tagmn[p]=inf;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(p<<1,l,mid);
        build(p<<1|1,mid+1,r);
    }

    void Max_tag(int p,int v) {
        mx[p]=max(mx[p],v),mn[p]=max(mn[p],v);
        tagmx[p]=max(tagmx[p],v);tagmn[p]=max(tagmn[p],v);
    }

    void Min_tag(int p,int v) {
        mx[p]=min(mx[p],v),mn[p]=min(mn[p],v);
        tagmx[p]=min(tagmx[p],v),tagmn[p]=min(tagmn[p],v);
    }

    void push_down(int p) {
        if(tagmx[p]!=-inf) {
            Max_tag(p<<1,tagmx[p]);
            Max_tag(p<<1|1,tagmx[p]);
            tagmx[p]=-inf;
        }
        if(tagmn[p]!=inf) {
            Min_tag(p<<1,tagmn[p]);
            Min_tag(p<<1|1,tagmn[p]);
            tagmn[p]=inf;
        }
    }

    void Max(int p,int l,int r,int L,int R,int v) {
        if(L<=l&&r<=R) {
            Max_tag(p,v);
            return;
        }
        int mid=(l+r)>>1;push_down(p);
        if(L<=mid)Max(p<<1,l,mid,L,R,v);
        if(R>mid)Max(p<<1|1,mid+1,r,L,R,v);
        update(p);
    }

    void Min(int p,int l,int r,int L,int R,int v) {
        if(L<=l&&r<=R) {
            Min_tag(p,v);
            return;
        }
        int mid=(l+r)>>1;push_down(p);
        if(L<=mid)Min(p<<1,l,mid,L,R,v);
        if(R>mid)Min(p<<1|1,mid+1,r,L,R,v);
        update(p);
    }

    void print(int p,int l,int r) {
        if(l==r) {printf("%d\n",mx[p]);return;}
        int mid=(l+r)>>1;push_down(p);
        print(p<<1,l,mid),print(p<<1|1,mid+1,r);
    }
}T;

int main() {
    n=read(),m=read();T.build(1,1,n);
    for(int i=1;i<=m;i++) {
        int opt=read(),l=read()+1,r=read()+1,v=read();
        if(opt==1)T.Max(1,1,n,l,r,v);
        else T.Min(1,1,n,l,r,v);
    }T.print(1,1,n);
    return 0;
}