网上有许多题,就是给定一个序列,要你支持几种操作: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。
第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。
对于每个第3种操作,给出正确的回答。
4 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4
2
【数据范围】
N<=50000,M<=100000。
Splay
加了点操作,多存点东西就可以了……pushdown多写点,函数大同小异…
代码:
#include
#include
#include
#include
using namespace std;
const int SZ = 1000010;
const int INF = 1000000010;
struct node{
node *ch[2],*f;
int sz,cnt,v,maxn,add;
bool flag;
void maintain()
{
sz = ch[0] -> sz + ch[1] -> sz + cnt;
maxn = max(v,max(ch[0] -> maxn,ch[1] -> maxn));
}
void setc(node *x,int d) { (ch[d] = x) -> f = this; }
void pushdown();
int dir() { return f -> ch[1] == this; }
}T[SZ], *root, *null;
int Tcnt = 0;
node* newnode(int x,node *fa)
{
node *k = T + (Tcnt ++);
k -> ch[1] = k -> ch[0] = null;
k -> cnt = k -> sz = 1;
k -> v = k -> maxn = x;
k -> f = fa;
k -> add = k -> flag = 0;
return k;
}
void node::pushdown()
{
if(flag)
{
flag = 0;
if(ch[0] != null) ch[0] -> flag ^= 1;
if(ch[1] != null) ch[1] -> flag ^= 1;
swap(ch[0],ch[1]);
}
if(add)
{
if(ch[0] != null) ch[0] -> add += add,ch[0] -> maxn += add,ch[0] -> v += add;
if(ch[1] != null) ch[1] -> add += add,ch[1] -> maxn += add,ch[1] -> v += add;
add = 0;
}
}
void rotate(node *p)
{
p -> f -> pushdown(); p -> pushdown();
node *fa = p -> f;
int d = p -> dir();
fa -> f -> setc(p,fa -> dir());
fa -> setc(p -> ch[d ^ 1],d); fa -> maintain();
p -> setc(fa,d ^ 1); p -> maintain();
if(fa == root) root = p;
}
void splay(node *p,node *rt = null)
{
while(p -> f != rt)
{
p -> pushdown();
if(p -> f -> f == rt) rotate(p);
else
{
if(p -> dir() == p -> f -> dir()) rotate(p -> f),rotate(p);
else rotate(p),rotate(p);
}
}
}
node* find(node *p,int k)
{
while(p != null)
{
p -> pushdown();
int l = p -> ch[0] -> sz + 1;
int r = p -> ch[0] -> sz + p -> cnt;
if(l <= k && k <= r) return p;
if(k > r) k -= r,p = p -> ch[1];
else p = p -> ch[0];
}
}
void change(node *p,int l,int r,int d)
{
l ++; r ++;
node *pre = find(root,l - 1);
node *suf = find(root,r + 1);
splay(pre); splay(suf,root);
root -> ch[1] -> ch[0] -> add += d;
root -> ch[1] -> ch[0] -> maxn += d;
root -> ch[1] -> ch[0] -> v += d;
}
void reverse(node *p,int l,int r)
{
l ++; r ++;
node *pre = find(root,l - 1);
node *suf = find(root,r + 1);
splay(pre); splay(suf,root);
root -> ch[1] -> ch[0] -> flag ^= 1;
}
int ask_max(node *p,int l,int r)
{
l ++; r ++;
node *pre = find(root,l - 1);
node *suf = find(root,r + 1);
splay(pre); splay(suf,root);
return root -> ch[1] -> ch[0] -> maxn;
}
int n,m;
void build(node* &p,int l,int r,node *fa)
{
if(l > r) return ;
int mid = (l + r) >> 1;
p = newnode(0,fa);
build(p -> ch[0],l,mid - 1,p);
build(p -> ch[1],mid + 1,r,p);
p -> maintain();
}
void init()
{
null = newnode(-INF,null);
null -> sz = null -> cnt = 0;
root = null;
root = newnode(-INF,null);
root -> ch[1] = newnode(INF,root);
build(root -> ch[1] -> ch[0],1,n,root -> ch[1]);
root -> ch[1] -> maintain();
root -> maintain();
}
int main()
{
scanf("%d%d",&n,&m);
init();
while(m --)
{
int k;
scanf("%d",&k);
int l,r,v;
if(k == 1)
{
scanf("%d%d%d",&l,&r,&v);
change(root,l,r,v);
}
else if(k == 2)
{
scanf("%d%d",&l,&r);
reverse(root,l,r);
}
else
{
scanf("%d%d",&l,&r);
printf("%d\n",ask_max(root,l,r));
}
}
return 0;
}