题目:
题解:
基本是模板题,维护区间最大值
记住build的时候update以及时刻pushdown
多update几下不会错的-------天宇哥哥
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#define N 50000
#define INF 1e9
using namespace std;
int ch[N+5][2],f[N+5],maxn[N+5],size[N+5],key[N+5],delta[N+5],deltafz[N+5],root,sz,a[N+5];
int get(int x){return ch[f[x]][1]==x;}
void updata(int x)
{
if (x)
{
maxn[x]=key[x];
if (ch[x][0]) maxn[x]=max(maxn[x],maxn[ch[x][0]]);
if (ch[x][1]) maxn[x]=max(maxn[x],maxn[ch[x][1]]);
size[x]=1;
if (ch[x][0]) size[x]+=size[ch[x][0]];
if (ch[x][1]) size[x]+=size[ch[x][1]];
}
}
void pushdown(int x)
{
if (delta[x])
{
if (ch[x][0]) delta[ch[x][0]]+=delta[x],key[ch[x][0]]+=delta[x],maxn[ch[x][0]]+=delta[x];
if (ch[x][1]) delta[ch[x][1]]+=delta[x],key[ch[x][1]]+=delta[x],maxn[ch[x][1]]+=delta[x];
delta[x]=0;
}
if (deltafz[x])
{
deltafz[x]=0;
swap(ch[x][1],ch[x][0]);
if (ch[x][0]) deltafz[ch[x][0]]^=1;
if (ch[x][1]) deltafz[ch[x][1]]^=1;
}
}
void rotate(int x)
{
pushdown(f[x]);
pushdown(x);
int old=f[x],oldf=f[old],which=get(x);
ch[old][which]=ch[x][which^1]; f[ch[x][which^1]]=old;
ch[x][which^1]=old; f[old]=x;
f[x]=oldf;
if (oldf) ch[oldf][ch[oldf][1]==old]=x;
updata(old);
updata(x);
}
void splay(int x,int tar)
{
for (int fa;(fa=f[x])!=tar;rotate(x))
if (f[fa]!=tar) rotate(get(x)==get(fa)?fa:x);
if (tar==0) root=x;
}
int build(int fa,int l,int r)
{
if (l>r) return 0;
int mid=(l+r)>>1;
int now=++sz; size[now]=1; f[now]=fa; key[now]=maxn[now]=a[mid];
int lch=build(now,l,mid-1);
int rch=build(now,mid+1,r);
ch[now][0]=lch; ch[now][1]=rch;
updata(now);
return now;
}
int find(int x)
{
int now=root;
while (1)
{
pushdown(now);
if (ch[now][0] && x<=size[ch[now][0]]) now=ch[now][0];
else
{
x-=size[ch[now][0]]+1;
if (!x) return now;
now=ch[now][1];
}
}
}
int main()
{
int n,m,i;
scanf("%d%d",&n,&m);
a[1]=-INF; a[n+2]=INF;
root=build(0,1,n+2);
for (i=1;i<=m;i++)
{
int opt,l,r,v;
scanf("%d",&opt);
scanf("%d%d",&l,&r);
int a1=find(l),a2=find(r+2);
splay(a1,0);
splay(a2,a1);
if (opt==1)
{
scanf("%d",&v);
delta[ch[ch[root][1]][0]]+=v;
maxn[ch[ch[root][1]][0]]+=v;
key[ch[ch[root][1]][0]]+=v;
updata(ch[root][1]);
updata(root);
}
else
if (opt==2)
deltafz[ch[ch[a1][1]][0]]^=1;
else
printf("%d\n",maxn[ch[ch[a1][1]][0]]);
}
}
本文介绍了一种使用线段树解决区间更新与查询问题的方法。通过维护区间最大值,实现高效的区间加法更新及区间最大值查询操作。文章提供了完整的C++代码实现,并详细解释了关键函数如旋转、下推、建立树等的功能。
2366

被折叠的 条评论
为什么被折叠?



