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]); } } }