UOJ 164 线段树历史最值

164. 【清华集训2015】V

描述
提交
自定义测试

Picks博士观察完金星凌日后,设计了一个复杂的电阻器。为了简化题目,题目中的常数与现实世界有所不同。

这个电阻器内有编号为 1∼n1∼n 的 nn 个独立水箱,水箱呈圆柱形,底面积为 1 m21 m2,每个水箱在顶部和底部各有一个阀门,可以让水以 1 m3/s1 m3/s 的流量通过,每个水箱的上阀门接水龙头,可以无限供应水,下阀门不接东西,可以让水流出。水箱顶部和底部都有一个接口,水的电阻率为 1 Ω⋅m1 Ω⋅m。

水箱的高度足够高,有一个导电浮标浮在水面上,通过导线与水箱顶的接口相连。一开始时第 ii 个水箱中有 ai m3ai m3 的水。

Picks博士接下来就需要对这个复杂的电阻器进行调试。他会进行以下五种操作。

1、打开编号在 [l,r][l,r] 中的所有水箱的上方阀门 xx 秒,然后关上它们的上方阀门。

2、打开编号在 [l,r][l,r] 中的所有水箱的下方阀门 xx 秒,然后关上它们的下方阀门。

3、将编号在 [l,r][l,r] 中的所有水箱的下方阀门与大海通过连通器以一定方式相连,使得这些水箱中都恰拥有 x m3x m3 的水,然后关上它们的下方阀门,撤去连通器。

4、在第 yy 个水箱的上下方接口处接上一个电动势为 1 V1 V 的电源,电源没有内阻,Picks博士会测量出通过电源的电流大小,之后撤去该电源。

5、由于水浸泡过的地方会留下明显的水渍而没有被水浸泡过的地方不会有,Picks博士可以据此测量出此时第 yy 个水箱的水渍高度,以推断曾经最多有多少水,节约他的建造成本。

现在,他请你来帮他做预实验,你能告诉他每次测量得到的电流大小以及测量得到的最多的水量是多少吗?
输入格式

第一行两个数:n,mn,m。

接下来一行 nn 个数,第 ii 个数表示初始时第 ii 个水箱内有 ai m3ai m3 的水。

接下来 mm 行中,第 ii 行第一个数 titi 表示操作类型:

若 ti=1ti=1,则接下来三个整数 li,ri,xili,ri,xi,表示打开编号在 [li,ri][li,ri] 中的所有水箱的上方接口 xixi 秒。

若 ti=2ti=2,则接下来三个整数 li,ri,xili,ri,xi,表示打开编号在 [li,ri][li,ri] 中的所有水箱的下方接口 xixi 秒。

若 ti=3ti=3,则接下来三个整数 li,ri,xili,ri,xi,表示将编号在 [li,ri][li,ri] 中的所有水箱与大海连接,使这些水箱中都恰有 xi m3xi m3 的水。

若 ti=4ti=4,则接下来一个整数 yiyi,表示测量在第 yiyi 个水箱的上下方接口处接上一个电动势为 1 V1 V 的电源时通过电源的电流。

若 ti=5ti=5,则接下来一个整数 yiyi,表示测量此时在第 yiyi 个水箱中的水渍高度。
输出格式

对于每个 ti=4ti=4,输出一个整数表示通过电源的电流大小的倒数(单位为 A−1A−1 ),如果电流为无穷大则输出0。

对于每个 ti=5ti=5,输出一个整数表示在第 yiyi 个水箱中的水渍高度(单位为 mm )。
样例输入一

5 6
1 2 3 4 5
2 1 3 2
4 1
1 1 4 1
5 3
3 1 5 4
4 2

样例输出一

0
3
4

样例输入二

见相关文件下载
样例输出二

见相关文件下载
样例输入三

见相关文件下载
样例输出三

见相关文件下载
限制与约定

时间限制:2s2s

空间限制:128MB128MB
测试点编号 n=n= m=m= 约定
1 10001000 10001000
2 10001000 10001000
3 105105 105105 没有操作2
4 5×1055×105 5×1055×105 没有操作2
5 105105 105105 没有操作1与操作5
6 105105 105105 没有操作1
7 5×1055×105 5×1055×105 没有操作1
8 5×1055×105 5×1055×105 没有操作5
9 105105 105105
10 5×1055×105 5×1055×105

对于所有的数据:1≤n,m≤5×105, 0≤ai,xi≤109,1≤li≤ri≤n, 1≤yi≤n1≤n,m≤5×105, 0≤ai,xi≤109,1≤li≤ri≤n, 1≤yi≤n.
提示

可能用到的物理公式:

1、欧姆定律:I=URI=UR,其中 I,U,RI,U,R 分别代表电流、电压和电阻。

2、电阻率公式:R=ρLSR=ρLS,其中 R,ρ,L,SR,ρ,L,S 分别代表电阻、电阻率、电阻长度、横截面积。

用了一个神奇的标记,网上有很多解释!!!

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>

using namespace std;

#define lc (o<<1)
#define rc (o<<1|1)
#define mid ((L+R)>>1)
#define LL long long
#define pb push_back
#define Set(a, v) memset(a, v, sizeof(a))
#define For(i, a, b) for(int i = (a); i <= (int)(b); i++)
#define Forr(i, a, b) for(int i = (a); i >= (int)(b); i--)

#define INF (1LL<<60)
#define MAXN (500000+5)

void read(int &x){
    char ch = getchar();
    while(ch < '0' || ch > '9') ch = getchar();

    x = 0;
    while(ch >= '0' && ch <= '9'){
        x = x*10+ch-'0';
        ch = getchar();
    }
}

struct Tage{
    LL a, b, ma, mb;

    Tage operator +=(const Tage &tmp){
        Tage ret;
        ret.a = max(tmp.a+a, -INF); //in order to not be bombed
        ret.b = max(b+tmp.a, tmp.b);
        ret.ma = max(a+tmp.ma, ma); 
        ret.mb = max(mb, max(tmp.mb, b+tmp.ma));

        a = ret.a; b = ret.b; ma = ret.ma; mb = ret.mb;
    }
};

int ql, qr;

struct Seg_tree{
    Tage t[MAXN*4];

    void build(int o, int L, int R){
        t[o] = (Tage){0, -INF, 0, -INF};
        if(L == R) return;
        build(lc, L, mid); build(rc, mid+1, R);
    }

    void pushdown(int o){
        t[lc] += t[o]; t[rc] += t[o];
        t[o] = (Tage){0, -INF, 0, -INF};
    }

    void modify(int o, int L, int R, Tage tag){
        if(ql <= L && qr >= R){
            t[o] += tag; return;
        }

        pushdown(o);
        if(ql <= mid) modify(lc, L, mid, tag);
        if(qr > mid) modify(rc, mid+1, R, tag);
    }

    Tage query(int o, int L, int R, int pos){ //query one node (pos)
        if(L == R) return t[o];
        pushdown(o);

        if(pos <= mid) return query(lc, L, mid, pos);
        return query(rc, mid+1, R, pos);
    }
}ST;

int main(){
    int n, m;

    read(n); read(m);
    ST.build(1, 1, n);

    For(i, 1, n){
        int tmp;
        read(tmp);
        ql = qr = i;
        ST.modify(1, 1, n, (Tage){tmp, -INF, tmp, -INF});
    }

    int type, L, R, rx;
    Tage ans;
    LL x;

    while(m--){
        read(type); 

        if(type <= 3){
            read(ql); read(qr); read(rx);
            x = rx;

            if(type == 1) ST.modify(1, 1, n, (Tage){x, -INF, x, -INF});
            else if(type == 2) ST.modify(1, 1, n, (Tage){-x, 0, -x, 0});
            else ST.modify(1, 1, n, (Tage){-INF, x, -INF, x});
        }else{
            read(rx);
            ans = ST.query(1, 1, n, rx);

            if(type == 4) printf("%lld\n", max(ans.a, ans.b));
            else printf("%lld\n", max(ans.ma, ans.mb));
        }
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值