Description
网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。一看另一道题,又是一个序列 要支持几种操作:D、C、B、A。尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。这道题目 就叫序列终结者吧。 【问题描述】 给定一个长度为N的序列,每个序列的元素是一个整数(废话)。要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V。 2. 将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。 3. 求[L,R]这个区间中的最大值。 最开始所有元素都是0。
Input
第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。
Output
对于每个第3种操作,给出正确的回答。
Sample Input
4 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4
Sample Output
2
【数据范围】
N<=50000,M<=100000。
splay区间操作模板
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#define MAXN (1000000+10)
using namespace std;
int Father[MAXN];
int Son[MAXN][2];
int Key[MAXN];
int Size[MAXN];
int Root,sz,n,m;
int Max[MAXN],Val[MAXN],Add[MAXN],Rev[MAXN];
using namespace std;
inline int Get(int x)
{
return Son[Father[x]][1]==x;
}
inline void Update(int x)
{
Size[x]=Size[Son[x][0]]+Size[Son[x][1]]+1;
Max[x]=max(Val[x],max(Max[Son[x][0]],Max[Son[x][1]]));
}
inline void Pushdown(int x)
{
if (Add[x])
{
if (Son[x][0])
{
Max[Son[x][0]]+=Add[x];
Val[Son[x][0]]+=Add[x];
Add[Son[x][0]]+=Add[x];
}
if (Son[x][1])
{
Max[Son[x][1]]+=Add[x];
Val[Son[x][1]]+=Add[x];
Add[Son[x][1]]+=Add[x];
}
Add[x]=0;
}
if (Rev[x])
{
Rev[x]=0;
swap(Son[x][0],Son[x][1]);
Rev[Son[x][0]]^=1;
Rev[Son[x][1]]^=1;
}
}
inline void Rotate(int x)
{
Pushdown(Father[x]);
Pushdown(x);
int wh=Get(x);
int fa=Father[x],fafa=Father[fa];
Son[fa][wh]=Son[x][wh^1];
Father[fa]=x;
if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
Son[x][wh^1]=fa;
Father[x]=fafa;
if (fafa) Son[fafa][Son[fafa][1]==fa]=x;
Update(fa);
Update(x);
}
inline void Splay(int x,int tar)
{
for (int fa;(fa=Father[x])!=tar;Rotate(x))
if (Father[fa]!=tar)
Rotate(Get(fa)==Get(x)?fa:x);
if (!tar) Root=x;
}
void Build(int l,int r,int fa)
{
if (l>r) return;
if (l==r)
{
Size[l]=1;
Father[l]=fa;
Son[fa][l>fa]=l;
return;
}
int mid=(l+r)>>1;
Build(l,mid-1,mid);
Build(mid+1,r,mid);
Father[mid]=fa;
Son[fa][mid>fa]=mid;
Update(mid);
}
int Findx(int x)
{
int now=Root;
while (1)
{
Pushdown(now);
if (Size[Son[now][0]]>=x)
now=Son[now][0];
else
{
x-=Size[Son[now][0]];
if (x==1)
{
Splay(now,0);
return now;
}
x--;
now=Son[now][1];
}
}
}
inline int Split(int x,int y)
{
int xx=Findx(x),yy=Findx(y);
Splay(xx,0);
Splay(yy,xx);
return Son[yy][0];
}
int main()
{
int p,l,r,x;
scanf("%d%d",&n,&m);
Build(1,n+2,0);
Root=(n+3)>>1;
Max[0]=-0x7fffffff;
for (int i=1;i<=m;++i)
{
scanf("%d",&p);
if (p==1)
{
scanf("%d%d%d",&l,&r,&x);
int node=Split(l,r+2);
Val[node]+=x;
Max[node]+=x;
Add[node]+=x;
}
if (p==2)
{
scanf("%d%d",&l,&r);
int node=Split(l,r+2);
Rev[node]^=1;
}
if (p==3)
{
scanf("%d%d",&l,&r);
int node=Split(l,r+2);
printf("%d\n",Max[node]);
}
}
}