HDU 5306 (线段树维护区间最值)

题意:
             一个 n n 个数的数组,m次操作,操作分三种:
1 x y v 1   x   y   v : 对于 i[x,y],ai=min(ai,val) i ∈ [ x , y ] , a i = m i n ( a i , v a l )
2 x y 2   x   y : max{ai |i[x,y]} m a x { a i   | i ∈ [ x , y ] }
3 x y 3   x   y : i=xyai ∑ i = x y a i

思路:
             看的论文。哎蒟蒻实在是没这个想法。
这里写图片描述
             然后就是卡我常数卡的比较严重。 要加输入输出挂才能过。

#include<bits/stdc++.h>
typedef long long ll;
const ll INF = 1e18 + 10;
const int maxn = 1e6 + 10;
using namespace std;

typedef pair<ll, ll> pa;
struct Node { ll fmax, smax, lazy, sum, tot; } seg[maxn * 4];
ll rec[maxn], a[10];

void do_it(pa &ans, ll val) {
    if(val > ans.first) {
        ans.second = ans.first;
        ans.first = val;
    } else if(val < ans.first && val > ans.second) ans.second = val;
}

pa find_max(int o1, int o2) {
    int num = 0;
    pa ans(-INF, -INF);
    do_it(ans, seg[o1].fmax);
    do_it(ans, seg[o2].fmax);
    if(seg[o1].smax != -INF) do_it(ans, seg[o1].smax);
    if(seg[o2].smax != -INF) do_it(ans, seg[o2].smax);

    return ans;
}

void push_up(int o) {
    int o1 = o << 1, o2 = o << 1 | 1;
    pa fd = find_max(o1, o2);
    seg[o].fmax = fd.first;
    seg[o].smax = fd.second;
    seg[o].sum = seg[o].tot = 0;
    if(seg[o].fmax == seg[o1].fmax) seg[o].tot += seg[o1].tot;
    if(seg[o].fmax == seg[o2].fmax) seg[o].tot += seg[o2].tot;
    seg[o].sum = seg[o1].sum + seg[o2].sum;
}

void build(int o, int l, int r) {
    seg[o].lazy = INF;
    if(l == r) {
        seg[o].fmax = rec[l];
        seg[o].smax = -INF;
        seg[o].sum = rec[l];
        seg[o].tot = 1;
        return ;
    }
    int mid = (l + r) >> 1;
    build(o << 1, l, mid);
    build(o << 1 | 1, mid + 1, r);
    push_up(o);
}

void update_lazy(int o, ll val) {
    if(val >= seg[o].fmax) return ;
    if(val > seg[o].smax && val < seg[o].fmax) {
        seg[o].lazy = min(val, seg[o].lazy);
        seg[o].sum += seg[o].tot * (val - seg[o].fmax);
        seg[o].fmax = val;
        return ;
    } else return ;
}

void push_down(int o) {
    if(seg[o].lazy == INF) return ;
    int o1 = o << 1, o2 = o << 1 | 1;
    update_lazy(o1, seg[o].lazy);
    update_lazy(o2, seg[o].lazy);
    seg[o].lazy = INF;
}

void update(int o, int l, int r, int ql, int qr, ll val) {
    if(l > qr || r < ql) return ;
    int mid = (l + r) >> 1;
    if(l >= ql && r <= qr) {
        if(val > seg[o].smax) { update_lazy(o, val); return ; }
        else {
            push_down(o);
            update(o << 1, l, mid, ql, qr, val);
            update(o << 1 | 1, mid + 1, r, ql, qr, val);
            push_up(o);
        }
        return ;
    }
    push_down(o);
    update(o << 1, l, mid, ql, qr, val);
    update(o << 1 | 1, mid + 1, r, ql, qr, val);
    push_up(o);
}

ll query(int o, int l, int r, int ql, int qr, int flag) {
    if(l > qr || r < ql) return 0;
    if(l >= ql && r <= qr) {
        if(flag == 1) return seg[o].sum; ///区间和
        if(flag == 0) return seg[o].fmax; ///区间最值
    }
    int mid = (l + r) >> 1;
    push_down(o);
    ll p1 = query(o << 1, l, mid, ql, qr, flag);
    ll p2 = query(o << 1 | 1, mid + 1, r, ql, qr, flag);
    if(flag == 1) return p1 + p2;
    else return max(p1, p2);
    push_up(o);
}

int n, m, T, kase = 1;

const int MAX = 10000;
char buf[MAX], *ps = buf, *pe = buf + 1;
inline void rnext() {
    if(++ps == pe) pe = (ps = buf) + fread(buf, sizeof(char), sizeof(buf) / sizeof(char), stdin);
}
template <class T>
inline bool in(T &ans) {
    ans = 0;
    T f = 1;
    if(ps == pe) return false;//EOF
    do{
        rnext();
        if('-' == *ps) f = -1;
    } while(!isdigit(*ps) && ps != pe);
    if(ps == pe) return false;//EOF
    do {
        ans = (ans<<1)+(ans<<3)+*ps-48;
        rnext();
    } while(isdigit(*ps) && ps != pe);
    ans *= f;
    return true;
}

///主函数最后调用write()方法
char bufout[MAX], outtmp[50],*pout = bufout, *pend = bufout + MAX;
inline void write() {
    fwrite(bufout, sizeof(char), pout - bufout, stdout);
    pout = bufout;
}
inline void out_char(char c) { *(pout++) = c; if(pout == pend) write();}
inline void out_str(char *s) {
    while(*s) {
        *(pout++) = *(s++);
        if(pout == pend) write();
    }
}
template <class T>
inline void out_int(T x) {
    if(!x) {
        out_char('0');
        return;
    }
    if(x < 0) x = -x,out_char('-');
    int len = 0;
    while(x) {
        outtmp[len++] = x%10+48;
        x /= 10;
    }
    outtmp[len] = 0;
    for(int i = 0, j = len - 1; i < j; i++,j--) swap(outtmp[i],outtmp[j]);
    out_str(outtmp);
}


int main() {
    in(T);
    while(T--) {
        in(n); in(m);
        for(int i = 0; i < n; i++) in(rec[i]);
        build(1, 0, n - 1);
        while(m--) {
            int op, x, y; ll val;
            in(op);
            if(!op) {
                in(x); in(y); in(val);
                update(1, 0, n - 1, x - 1, y - 1, val);
            } else {
                in(x); in(y);
                ll ans = query(1, 0, n - 1, x - 1, y - 1, op - 1);
                out_int(ans);
                out_char('\n');
            }
        }
    }
    write();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值