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)\)。

  要查询单点值的话只要把所有标记都下放了就好了。

  这种标记也支持取\(\max\)。即,\(\max\{(a,b),(c,d)\}=(\max\{a,c\},\max\{b,d\})\)。本质上就是一个分段函数取\(\max\)的过程。

  所以最后一问再维护一个历史最大值这道题就做完了。注意下传标记时先传历史标记。

  还有一个要注意的地方:标记\((a,b)\)里的\(a\)实际上是\(\max\{a,-inf\}\)。注意修改的时候和\(-inf\)取个\(max\),不然很容易就爆掉了。

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define max(a,b) (a>b?a:b)
#define maxn 500010
#define INF (1LL<<60)

using namespace std;
typedef long long llg;

int n,m,L,R;
llg na[maxn<<2],nb[maxn<<2];
llg pa[maxn<<2],pb[maxn<<2],za,zb;

int getint(){
	int w=0;bool q=0;
	char c=getchar();
	while((c>‘9‘||c<‘0‘)&&c!=‘-‘) c=getchar();
	if(c==‘-‘) c=getchar(),q=1;
	while(c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar();
	return q?-w:w;
}

void pushdown(int u){
	for(int i=0,v;v=u<<1|i,i<2;i++){
		pa[v]=max(pa[v],pa[u]+na[v]);
		pb[v]=max(pb[v],max(pb[u],nb[v]+pa[u]));
		na[v]=max(na[v]+na[u],-INF);
		nb[v]=max(nb[v]+na[u],nb[u]);
	}
	na[u]=nb[u]=pa[u]=pb[u]=0;
}

void build(int u,int l,int r){
	int lc=u<<1,lv=u<<1|1,mid=(l+r)>>1;
	if(l==r) na[u]=pa[u]=getint();
	else build(lc,l,mid),build(lv,mid+1,r);
}

void add(int u,int l,int r){
	int lc=u<<1,lv=u<<1|1,mid=(l+r)>>1;
	if(L<=l && r<=R){
		na[u]=max(na[u]+za,-INF);
		nb[u]=max(nb[u]+za,zb);
		pa[u]=max(pa[u],na[u]);
		pb[u]=max(pb[u],nb[u]);
		return;
	}
	pushdown(u);
	if(L<=mid) add(lc,l,mid);
	if(R>mid) add(lv,mid+1,r);
}

void query(bool w){
	int u=1,l=1,r=n,mid;
	while(l!=r){
		mid=(l+r)>>1;
		pushdown(u); u<<=1;
		if(L<=mid) r=mid;
		else u|=1,l=mid+1;
	}
	za=w?na[u]:pa[u];
	zb=w?nb[u]:pb[u];
}

int main(){
	File("a");
	n=getint(),m=getint();
	build(1,1,n);
	while(m--){
		int ty=getint(),x;
		if(ty<=3){
			L=getint(),R=getint();x=getint();
			if(ty==1) za=x,zb=0;
			if(ty==2) za=-x,zb=0;
			if(ty==3) za=-INF,zb=x;
			add(1,1,n);
		}
		else{
			L=R=getint(); query(ty==4);
			printf("%lld\n",max(za,zb));
		}
	}
	return 0;
}
时间: 2024-10-09 22:34:21

UOJ #164 【清华集训2015】 V的相关文章

清华集训2015 V

#164. [清华集训2015]V http://uoj.ac/problem/164 统计 描述 提交 自定义测试 Picks博士观察完金星凌日后,设计了一个复杂的电阻器.为了简化题目,题目中的常数与现实世界有所不同. 这个电阻器内有编号为 1∼n1∼n 的 nn 个独立水箱,水箱呈圆柱形,底面积为 1 m21 m2,每个水箱在顶部和底部各有一个阀门,可以让水以 1 m3/s 的流量通过,每个水箱的上阀门接水龙头,可以无限供应水,下阀门不接东西,可以让水流出.水箱顶部和底部都有一个接口,水的电

[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

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

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

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

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

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) 只要记录历史最大

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

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

bzoj 3816&amp;&amp;uoj #41. [清华集训2014]矩阵变换

稳定婚姻问题: 有n个男生,n个女生,所有女生在每个男生眼里有个排名,反之一样. 将男生和女生两两配对,保证不会出现婚姻不稳定的问题. 即A-1,B-2 而A更喜欢2,2更喜欢A. 算法流程: 每次男生向自己未追求过的排名最高女生求婚. 然后每个有追求者的女生在自己现男友和追求者中选择一个最喜欢的接受,然后拒绝其他人. 算法一定可以结束. 因为如果最后有一个男生单身,那他一定把所有女生都追求过一遍,说明没有女生单身,产生矛盾. #include<iostream> #include<cs

线性基 uoj 36 清华集训2014 玛里苟斯

http://uoj.ac/problem/36 感觉挺可做的但是不会.. \(k=1\)按位扫就好了 出现\(1\)概率就是\(0.5\) \(k=2\)要特殊处理 设xor后的数是\(b_1 b_2 \dots b_n\) 计算平方贡献就好了\(\sum_{i,j}b_i b_j 2^{i+j}*p\) \(p\)存在一位\(i\),\(j\)不同的话是1/4 否则就是1/2 \(k\geq3\) 首先要知道随机选数的话 如果维护的集合可以通过xor算子得到\(x\) 那么\(x\)与答案无

UOJ.41.[清华集训2014]矩阵变换(稳定婚姻)

题目链接 稳定婚姻问题:有n个男生n个女生,每个男/女生对每个女/男生有一个不同的喜爱程度.给每个人选择配偶. 若不存在 x,y未匹配,且x喜欢y胜过喜欢x当前的配偶,y喜欢x也胜过y当前的配偶 的完备匹配,则称这是一个稳定匹配. 稳定匹配一定存在,且存在一个\(O(n^2)\)的算法: 任选一个未匹配的男生x,按x的喜爱程度从大到小枚举每个女生,若当前女生没有配偶或喜欢x胜过喜欢当前配偶,则与x匹配.直到所有男生都匹配. 这一题我们用行表示男生,n个数表示女生.喜爱程度为:行更喜欢靠前的数,数