清华集训2015 V

#164. 【清华集训2015】V

http://uoj.ac/problem/164

统计

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

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

水箱的高度足够高,有一个导电浮标浮在水面上,通过导线与水箱顶的接口相连。一开始时第 ii 个水箱中有 ai 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

样例输入二

见相关文件下载

样例输出二

见相关文件下载

样例输入三

见相关文件下载

样例输出三

见相关文件下载

限制与约定

时间限制:2s

空间限制:128MB

测试点编号 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 分别代表电阻、电阻率、电阻长度、横截面积。

下载

相关文件下载

神奇的搞了一个标记(a,b),表示x=max{x+a,b}

统一了赋值、加减、查询操作,orz

区间加w:标记(w,0)

区间减w,再跟0取max:标记(-w,0)

区间赋值w:标记(-inf,w)

查询操作:维护当前的a,当前的b,历史最大的a,历史最大的b

标记的合并:

假设x原有标记(a,b),现在又来了一个标记(c,d)

原来的x=max{x+a,b}

现在x=max{x+a+c,b+c,d}=max{x+a+c,max(b+c,d)}

标记的下传:

先下传历史标记,再下传当前标记

若父节点有标记,那构成这个标记的所有操作一定在子节点标记后面,否则这个标记早就被传了下去

假设构成子节点标记的操作序列为[1,r],构成父节点标记的操作序列为[L,R],那么1<r<L<R

更新子节点历史标记:子节点的历史最大值应该在 操作序列[1,r]  和  操作序列[1,R]  中取最大

操作序列[1,r]就是子节点的标记,

操作序列[1,R]就是 标记[1,r]与标记[L,R]的合并,把[1,r]看作原有标记,把[L,R]看作又来的标记

更新子节点现有标记:两个标记直接加,然后取大即可

注意区间减w,可能会减爆设置的极小值,所以涉及到a的直接赋值操作都对-inf取max

每个点的初始标记为(0,0),每个点的初始值赋给a,那么实际代码中对标记的操作可以把x去掉

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#define N 500001
#define inf (1LL<<62)
using namespace std;
int n,m;
long long ansa,ansb;
struct node
{
    int l,r;
    long long na,nb,ha,hb;
    bool f;
}tr[N*4];
void build(int k,int l,int r)
{
    tr[k].l=l; tr[k].r=r;
    if(l==r)
    {
        scanf("%lld",&tr[k].na);
        tr[k].ha=tr[k].na;
        return;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
}
void down(int k)
{
    for(int i=0,z;z=k<<1|i,i<2;i++)
    {
        tr[z].ha=max(tr[z].ha,tr[k].ha+tr[z].na);
        tr[z].hb=max(tr[z].hb,max(tr[z].nb+tr[k].ha,tr[k].hb));
        tr[z].na=max(tr[z].na+tr[k].na,-inf);
        tr[z].nb=max(tr[z].nb+tr[k].na,tr[k].nb);
    }
    tr[k].na=tr[k].nb=tr[k].ha=tr[k].hb=0;
    tr[k].f=0;
    tr[k<<1].f=tr[k<<1|1].f=1;
}
void change(int k,int l,int r,long long a,long long b)
{
    if(tr[k].l>=l&&tr[k].r<=r)
    {
        tr[k].na=max(tr[k].na+a,-inf);
        tr[k].nb=max(tr[k].nb+a,b);
        tr[k].ha=max(tr[k].ha,tr[k].na);
        tr[k].hb=max(tr[k].hb,tr[k].nb);
        tr[k].f=true;
        return;
    }
    if(tr[k].f) down(k);
    int mid=tr[k].l+tr[k].r>>1;
    if(l<=mid) change(k<<1,l,r,a,b);
    if(r>mid) change(k<<1|1,l,r,a,b);
}
void query(int k,int p,int w)
{
    if(tr[k].l==tr[k].r)
    {
        ansa= w==4 ? tr[k].na : tr[k].ha;
        ansb= w==4 ? tr[k].nb : tr[k].hb;
        return;
    }
    if(tr[k].f) down(k);
    int mid=tr[k].l+tr[k].r>>1;
    if(p<=mid) query(k<<1,p,w);
    else query(k<<1|1,p,w);
}
int main()
{
    scanf("%d%d",&n,&m);
    build(1,1,n);
    int op,l,r,x;
    while(m--)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d%d%d",&l,&r,&x);
            change(1,l,r,x,0);
        }
        else if(op==2)
        {
            scanf("%d%d%d",&l,&r,&x);
            change(1,l,r,-x,0);
        }
        else if(op==3)
        {
            scanf("%d%d%d",&l,&r,&x);
            change(1,l,r,-inf,x);
        }
        else if(op==4)
        {
            scanf("%d",&l);
            query(1,l,4);
            printf("%lld\n",max(ansa,ansb));
        }
        else
        {
            scanf("%d",&l);
            query(1,l,5);
            printf("%lld\n",max(ansa,ansb));
        }
    }
} 
时间: 2024-08-22 13:12:02

清华集训2015 V的相关文章

[uoj164][清华集训2015]V——线段树

题目大意: 传送门 思路: 对于这么多的操作,以及询问时的取历史最大值,用一般的线段树显然不太好做. 于是考虑把每个操作转化成\(h_i=\max(h_i+a,b)\)的形式,不难发现第一种和第二种就是\(h_i=\max(h_i+x,0)\),第三种即\(h_i=\max(h_i-inf,x)\). 于是我们在线段树上对于每一个节点维护这两个标记,考虑如何合并标记: \[\begin{aligned} x &=\max(\max(x+a,b)+a',b')\ & =\max(\max(x

uoj164. 【清华集训2015】V 统计

坑爹题面:http://uoj.ac/problem/164 正常题面: 对于一个序列支持下列5个操作: 1.区间加x 2.区间减x并与0取max 3.区间覆盖 4.单点查询 5.单点历史最大值查询 题解: 每个区间维护一个标记函数f(x)=max(x+a,b) 那么两个标记 f 和 g 的合并就是f(g(x))=max(x+max(fa+ga,-inf),max(fb+ga,gb))(假设f在前g在后) 区间加减就是打上max(x,0),区间覆盖就是打上max(-inf,x) 只要记录历史最大

UOJ #164 【清华集训2015】 V

题目链接:V 这道题由于是单点询问,所以异常好写. 注意到每种修改操作都可以用一个标记\((a,b)\)表示.标记\((a,b)\)的意义就是\(x=\max\{x+a,b\}\) 同时这种标记也是支持合并的.有\((a,b)+(c,d)=(a+c,\max\{b+c,d\})\) 用上这种标记的话,\(1\)操作就是\((x,0)\),\(2\)操作就是\((-x,0)\),\(3\)操作就是\((-inf,x)\). 要查询单点值的话只要把所有标记都下放了就好了. 这种标记也支持取\(\ma

UOJ #164 【清华集训2015】V (线段树)

题目链接 http://uoj.ac/problem/164 题解 神仙线段树题. 首先赋值操作可以等价于减掉正无穷再加上\(x\). 假设某个位置从前到后的操作序列是: \(x_1,x_2,...,x_k\) 那么则有: 当前值就是该序列的最大后缀和,历史最大值就是该序列的最大子段和! 然后如果把最大子段和定义加法,那么就变成了区间加单点查询. 直接线段树维护即可,时间复杂度\(O(n\log n)\). (好吧,其实似乎把赋值看做减去正无穷再加\(x\)似乎是可以被卡爆long long的-

#163. 【清华集训2015】新式计算机

//题目太长,为了我的小心脏,我都没忍心读下去...... 这是一道提交答案题. 伟大的人类智慧之神 clevertick 奋战三星期,造出了一台新式计算机(其实他造计算机只用了三天,剩余的时间都在编译.调试……),起名 CTOX.现在,他可以抛弃自己旧的机器,来用 CTOX 完成自己的工作了…… CTOX 拥有足够大(可以认为是无穷大)的内存,并且它的内存地址是二维的,也就是说,一个内存地址可以使用一对整数 (x,y)(x,y) 来表示,和这个地址相邻的4个地址分别是 (x+1,y)(x+1,

[清华集训2015]灯泡(浙江大学ZOJ 3203 Light Bulb)

Time Limit: 1 Second      Memory Limit: 32768 KB Compared to wildleopard's wealthiness, his brother mildleopard is rather poor. His house is narrow and he has only one light bulb in his house. Every night, he is wandering in his incommodious house, t

[UOJ 160][清华集训2015]斗地主

文字 数字 较多,加载略慢 题目链接 Emm怎么没人做啊,网上都找不到题解我怎么抄 首先大力模拟,写一个对抗搜索,记录当前玩家的牌,对手的牌,当前玩家,对手上一次出的牌 然后加一个记忆化搜索,这样可以轻松跑出前两个Subtask(当然你可以加上O2优化跑得快一点) 然后我大力跑一下Subtask3,每个点都在\(1s~2s\)左右,然后跑了几十分钟也跑出来了 当然或许是因为i5-8250U然后开一大堆窗口的原因(复杂度爆炸(不过低压U确实慢 然后改成二分答案+判定,这样可以在搜索时加很多剪枝,比

bzoj 4736 /uoj274【清华集训2016】温暖会指引我们前行 lct

[清华集训2016]温暖会指引我们前行 统计 描述 提交 自定义测试 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出无助的哀嚎 “冻死宝宝了!” 这时 远处的天边出现了一位火焰之神 “我将赐予你们温暖和希望!” 只见他的身体中喷射出火焰之力 通过坚固的钢铁,传遍了千家万户 这时,只听见人们欢呼 “暖气来啦!” 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很低. 小R的

uoj 41 【清华集训2014】矩阵变换 婚姻稳定问题

[清华集训2014]矩阵变换 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/41 Description 给出一个 N 行 M 列的矩阵A, 保证满足以下性质: M>N.    矩阵中每个数都是 [0,N] 中的自然数.    每行中, [1,N] 中每个自然数都恰好出现一次.这意味着每行中 0 恰好出现 M−N 次.    每列中,[1,N] 中每个自然数至多出现一次. 现在我们要在每行中选取一个非零数,