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
Sample Output
2
【数据范围】
N<=50000,M<=100000。
分析
一大清早就A了一题,身心愉悦
splay大法好
代码
#include <bits/stdc++.h>
#define N 50005
#define INF 0x7fffffff
struct NODE
{
int son[2];
int fa;
int size;
int mx, cover;
int lazy;
bool rev;
}t[N];
int root;
int size;
int id[N];
int read()
{
int x = 0,f = 1;
int ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
void pushDown(int k)
{
int l = t[k].son[0];
int r = t[k].son[1];
int tmp = t[k].lazy;
if (tmp)
{
t[k].lazy = 0;
if (l)
{
t[l].mx += tmp;
t[l].lazy += tmp;
t[l].cover += tmp;
}
if (r)
{
t[r].mx += tmp;
t[r].lazy += tmp;
t[r].cover += tmp;
}
}
if (t[k].rev)
{
t[k].rev = 0;
t[l].rev ^= 1;
t[r].rev ^= 1;
std::swap(t[k].son[0],t[k].son[1]);
}
}
void pushUp(int k)
{
t[k].mx = std::max(t[t[k].son[0]].mx, t[t[k].son[1]].mx);
t[k].mx = std::max(t[k].mx, t[k].cover);
t[k].size = t[t[k].son[0]].size + t[t[k].son[1]].size + 1;
}
void rotate(int x,int &k)
{
int y = t[x].fa;
int z = t[y].fa;
int l,r;
if (t[y].son[0] == x)
l = 0;
else l = 1;
r = l ^ 1;
if (y == k)
k = x;
else
{
if (t[z].son[0] == y)
t[z].son[0] = x;
else t[z].son[1] = x;
}
t[x].fa = z;
t[y].fa = x;
t[t[x].son[r]].fa = y;
t[y].son[l] = t[x].son[r];
t[x].son[r] = y;
pushUp(y);
pushUp(x);
}
void splay(int x,int &k)
{
while (x != k)
{
int y = t[x].fa;
int z = t[y].fa;
if (y != k)
{
if (t[y].son[0] == x ^ t[z].son[0] == y)
{
rotate(x,k);
}
else rotate(y,k);
}
rotate(x,k);
}
}
int find(int k,int rank)
{
if (t[k].lazy || t[k].rev)
pushDown(k);
int l = t[k].son[0], r = t[k].son[1];
if (rank == t[l].size + 1)
return k;
else
if (rank <= t[l].size)
return find(l,rank);
else return find(r,rank - t[l].size - 1);
}
void add(int l,int r,int val)
{
int x = find(root,l);
int y = find(root,r + 2);
splay(x,root);
splay(y,t[x].son[1]);
int z = t[y].son[0];
t[z].lazy += val;
t[z].cover += val;
t[z].mx += val;
}
void rever(int l,int r)
{
int x = find(root,l);
int y = find(root,r + 2);
splay(x,root);
splay(y,t[x].son[1]);
t[t[y].son[0]].rev ^= 1;
}
void query(int l,int r)
{
int x = find(root,l);
int y = find(root,r + 2);
splay(x,root);
splay(y,t[x].son[1]);
printf("%d\n",t[t[y].son[0]].mx);
}
void build(int l,int r,int f)
{
if (l > r)
return;
int now = id[l];
int last = id[f];
if (l == r)
{
t[now].size = 1;
t[now].fa = last;
if (l < f)
t[last].son[0] = now;
else t[last].son[1] = now;
return;
}
int mid = (l + r) >> 1;
now = id[mid];
build(l,mid - 1,mid);
build(mid + 1,r,mid);
t[now].fa = last;
pushUp(now);
if (mid < f)
t[last].son[0] = now;
else t[last].son[1] = now;
}
int main()
{
t[0].mx = -INF;
int n,m;
n = read();
m = read();
for (int i = 1; i <= n + 2; i++)
id[i] = ++size;
build(1,n + 2,0);
root = (n + 3) >> 1;
for (int i = 1; i <= m; i++)
{
int opt,l,r,val;
opt = read();
if (opt == 1)
{
l = read();
r = read();
val = read();
add(l,r,val);
continue;
}
if (opt == 2)
{
l = read();
r = read();
rever(l,r);
continue;
}
if (opt == 3)
{
l = read();
r = read();
query(l,r);
}
}
}