uoj#164. 清华集训2015V
Posted thy_asdf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uoj#164. 清华集训2015V相关的知识,希望对你有一定的参考价值。
思路:科学的题面:
请你写一个数据结构支持以下功能:
1:区间[l,r]加x
2:区间[l,r]减x并和0取max
3:区间覆盖
4:单点询问
5:单点历史最大值询问
线段树维护分段函数
标记就是一个二元组(a,b)表示标记生效后x=max(x+a,b)
1操作就是打(x,0)的标记
2就是(-x,0)
3就是(-inf,v)
我们手推一下就可以发现这个标记是满足结合律和封闭性的
然后两个标记怎么合并呢?
g(f(x))=max(x+max(fa+ga,-inf),max(fb+ga,gb))(打f标记的时间在前,打g标记在后)
中间和-inf取max是为了不使多个-inf加爆了
对于历史最大值,我们要记录的是历史最大标记而不是直接在每个点记录历史最大值
为什么是这样的?
假设我们进行一次区间赋为inf的操作,接着有全部赋为0,标记还没来得及下传更新历史最大值就被后一个标记cha了
所以每个点记录历史最大值是错的
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define PI pair<long long,long long>
#define mp(a,b) make_pair(a,b)
#define fi first
#define se second
typedef long long ll;
const int maxn=500010;
const ll inf=4557430888798830399ll;
using namespace std;
int n,m,a[maxn];
PI max(PI a,PI b)return mp(max(a.fi,b.fi),max(a.se,b.se));
PI operator +(PI f,PI g)return mp(max(f.fi+g.fi,-inf),max(f.se+g.fi,g.se));
struct Tsegment
#define ls (p<<1)
#define rs ((p<<1)|1)
#define mid ((l+r)>>1)
PI now[maxn<<2],ever[maxn<<2];
void add(int p,int ch)
ever[ch]=max(ever[ch],now[ch]+ever[p]);
now[ch]=now[ch]+now[p];
void down(int p)
add(p,ls),add(p,rs);
now[p]=ever[p]=mp(0,0);
void build(int p,int l,int r)
if (l==r)now[p]=ever[p]=mp(a[l],0);return;
build(ls,l,mid),build(rs,mid+1,r);
void modify(int p,int l,int r,int a,int b,PI v)
//printf("p=%d l=%d r=%d a=%d b=%d\\n",p,l,r,a,b);
if (l==a&&r==b)
now[p]=now[p]+v;
ever[p]=max(ever[p],now[p]);
return;
down(p);
if (b<=mid) modify(ls,l,mid,a,b,v);
else if (a>mid) modify(rs,mid+1,r,a,b,v);
else modify(ls,l,mid,a,mid,v),modify(rs,mid+1,r,mid+1,b,v);
ll query(int p,int l,int r,int x,int op)
if (l==r)
if (op) return max(ever[p].fi,ever[p].se);
else return max(now[p].fi,now[p].se);
down(p);
if (x<=mid) return query(ls,l,mid,x,op);
else return query(rs,mid+1,r,x,op);
void cover(int l,int r,int v)modify(1,1,n,l,r,mp(-inf,v));
void inc(int l,int r,int v)modify(1,1,n,l,r,mp(v,0));
ll query(int x,int op)return query(1,1,n,x,op);
T;
int main()
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
T.build(1,1,n);
for (int i=1,l,r,x,op;i<=m;i++)
scanf("%d",&op);
if (op==1) scanf("%d%d%d",&l,&r,&x),T.inc(l,r,x);
else if (op==2) scanf("%d%d%d",&l,&r,&x),T.inc(l,r,-x);
else if (op==3) scanf("%d%d%d",&l,&r,&x),T.cover(l,r,x);
else if (op==4) scanf("%d",&x),printf("%lld\\n",T.query(x,0));
else if (op==5) scanf("%d",&x),printf("%lld\\n",T.query(x,1));
else if (op==6)
for (int i=1;i<=n;i++)
printf("%lld ",T.query(i,0));puts("");
else if (op==7)
for (int i=1;i<=n;i++)
printf("%lld ",T.query(i,1));puts("");
return 0;
/*
5 6
1 2 3 4 5
2 1 3 2 //0 0 1 4 5
4 1 //0
1 1 4 1 //1 1 2 5 6
5 3 //3
3 1 5 4 //4 4 4 4 4
4 2 //4
*/
以上是关于uoj#164. 清华集训2015V的主要内容,如果未能解决你的问题,请参考以下文章