Description
网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。一看另一道题,又是一个序列,要支持几种操作:D、C、B、A。尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样,我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。这道题目 就叫序列终结者吧。
【问题描述】
给定一个长度为
1. 将
2. 将
3. 求
Input
第一行两个整数
以下
Output
对于每个第
Sample Input
4 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4
Sample Output
2
【数据范围】
N<=50000,M<=100000。
HINT
Source
思路
splay。
区间反转和区间加?打标记,标记下传需要注意一下。
求最大值?splay每个节点维护一个最大值,注意更新。
代码
#include <cstdio>
const int maxn=100000;
int n;
struct splay_tree
{
int fa[maxn+10],son[2][maxn+10],size[maxn+10],val[maxn+10];
int maxx[maxn+10],lazy[maxn+10],rev[maxn+10],root;
inline int pushdown(int x)
{
if(rev[x])
{
int t=son[1][x];
son[1][x]=son[0][x];
son[0][x]=t;
rev[son[0][x]]^=1;
rev[son[1][x]]^=1;
rev[x]=0;
}
if(son[0][x])
{
val[son[0][x]]+=lazy[x];
lazy[son[0][x]]+=lazy[x];
maxx[son[0][x]]+=lazy[x];
}
if(son[1][x])
{
val[son[1][x]]+=lazy[x];
lazy[son[1][x]]+=lazy[x];
maxx[son[1][x]]+=lazy[x];
}
lazy[x]=0;
return 0;
}
inline int updata(int x)
{
size[x]=1;
maxx[x]=val[x];
if(son[0][x])
{
size[x]+=size[son[0][x]];
if(maxx[x]<maxx[son[0][x]])
{
maxx[x]=maxx[son[0][x]];
}
}
if(son[1][x])
{
size[x]+=size[son[1][x]];
if(maxx[x]<maxx[son[1][x]])
{
maxx[x]=maxx[son[1][x]];
}
}
return 0;
}
inline int t(int x)
{
return son[1][fa[x]]==x;
}
inline int rotate(int x)
{
int k=t(x),f=fa[x];
if(fa[f])
{
son[t(f)][fa[f]]=x;
}
fa[x]=fa[f];
if(son[!k][x])
{
fa[son[!k][x]]=f;
}
son[k][f]=son[!k][x];
fa[f]=x;
son[!k][x]=f;
updata(f);
updata(x);
return 0;
}
inline int splay(int x,int c)
{
while(fa[x]!=c)
{
int f=fa[x];
if(fa[f]==c)
{
rotate(x);
}
else if(t(x)==t(f))
{
rotate(f);
rotate(x);
}
else
{
rotate(x);
rotate(x);
}
}
if(!c)
{
root=x;
}
return 0;
}
inline int build(int l,int r)
{
int mid=(l+r)>>1;
val[mid]=0;
lazy[mid]=0;
if(l<=mid-1)
{
son[0][mid]=build(l,mid-1);
fa[son[0][mid]]=mid;
}
if(mid+1<=r)
{
son[1][mid]=build(mid+1,r);
fa[son[1][mid]]=mid;
}
updata(mid);
return mid;
}
inline int getkth(int x)
{
int now=root;
while(now)
{
pushdown(now);
if(size[son[0][now]]+1==x)
{
return now;
}
else if(size[son[0][now]]+1<x)
{
x-=size[son[0][now]]+1;
now=son[1][now];
}
else
{
now=son[0][now];
}
}
return 0;
}
inline int addnode(int x,int v)
{
lazy[x]+=v;
maxx[x]+=v;
val[x]+=v;
return 0;
}
inline int add(int l,int r,int v)
{
if(l==1)
{
if(r==n)
{
addnode(root,v);
}
else
{
int x=getkth(r+1);
splay(x,0);
addnode(son[0][x],v);
updata(x);
}
}
else
{
int x=getkth(l-1);
splay(x,0);
if(r==n)
{
addnode(son[1][x],v);
updata(x);
}
else
{
int y=getkth(r+1);
splay(y,x);
addnode(son[0][y],v);
updata(y);
updata(x);
}
}
return 0;
}
inline int reverse(int l,int r)
{
if(l==1)
{
if(r==n)
{
rev[root]^=1;
}
else
{
int x=getkth(r+1);
splay(x,0);
rev[son[0][x]]^=1;
}
}
else
{
int x=getkth(l-1);
splay(x,0);
if(r==n)
{
rev[son[1][x]]^=1;
}
else
{
int y=getkth(r+1);
splay(y,x);
rev[son[0][y]]^=1;
}
}
return 0;
}
inline int getmax(int l,int r)
{
if(l==1)
{
if(r==n)
{
return maxx[root];
}
else
{
int x=getkth(r+1);
splay(x,0);
return maxx[son[0][x]];
}
}
else
{
int x=getkth(l-1);
splay(x,0);
if(r==n)
{
return maxx[son[1][x]];
}
else
{
int y=getkth(r+1);
splay(y,x);
return maxx[son[0][y]];
}
}
}
};
splay_tree st;
int m,k,l,r,v;
int main()
{
scanf("%d%d",&n,&m);
st.build(1,n);
st.root=(n+1)>>1;
while(m--)
{
scanf("%d%d%d",&k,&l,&r);
if(k==1)
{
scanf("%d",&v);
st.add(l,r,v);
}
else if(k==2)
{
st.reverse(l,r);
}
else
{
printf("%d\n",st.getmax(l,r));
}
}
return 0;
}