1251: 序列终结者
Time Limit: 20 Sec
Memory Limit: 162 MB
Submit: 3284
Solved: 1338
[ Submit][ Status][ Discuss]
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
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
[ Submit][ Status][ Discuss]
sply维护几个标记就好
注意最大值的维护,苟弱在maintain和pushdown函数维护一下就解决了。。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5E4 + 50;
class data{
private:
struct Node{
Node *ch[2];
int ma,rev,add,siz,num;
}*root,*tot,pool[maxn];
void maintain(Node *&x) {
x->ma = x->num;
int s1 = 0;
if (x->ch[0] != NULL) {
s1 = x->ch[0]->siz;
x->ma = max(x->ma,x->ch[0]->ma);
}
int s2 = 0;
if (x->ch[1] != NULL){
s2 = x->ch[1]->siz;
x->ma = max(x->ma,x->ch[1]->ma);
}
x->siz = s1 + s2 + 1;
}
void pushdown(Node *&x) {
int ma = x->num;
if (x->rev) {
swap(x->ch[0],x->ch[1]);
x->rev = 0;
for (int i = 0; i < 2; i++)
if (x->ch[i] != NULL) x->ch[i]->rev ^= 1;
}
for (int i = 0; i < 2; i++)
if (x->ch[i] != NULL) {
x->ch[i]->ma += x->add;
x->ch[i]->add += x->add;
x->ch[i]->num += x->add;
ma = max(ma,x->ch[i]->ma);
}
x->add = 0;
x->ma = ma;
}
void rotate(Node *&x,int d) {
Node *y = x->ch[d];
x->ch[d] = y->ch[d^1];
y->ch[d^1] = x;
maintain(x);
x = y;
maintain(x);
}
void Insert(Node *&x) {
if (x == NULL) {
x = ++tot;
x -> ma = x->rev = x->add = x->num = 0;
x-> siz = 1;
return;
}
Insert(x->ch[1]);
maintain(x);
}
void splay(Node *&x,int rank) {
pushdown(x);
int s0 = (x->ch[0] == NULL)?0:x->ch[0]->siz;
if (s0 + 1 == rank) return;
int d = (rank < s0 + 1)?0:1;
if (d) rank = rank - s0 - 1;
Node *&y = x->ch[d];
pushdown(y);
int s1 = (y->ch[0] == NULL)?0:y->ch[0]->siz;
if (s1 + 1 != rank) {
int d2 = (rank < s1 + 1)?0:1;
if (d2) rank = rank - s1 - 1;
splay(y->ch[d2],rank);
if (d == d2) rotate(x,d);
else rotate(y,d2);
}
rotate(x,d);
}
public:
data() {
root = NULL; tot = pool;
}
void Ins (int rank) {
Insert(root);
splay(root,rank);
}
void spl(int a,int b) {
splay(root,a);
int s0 = (root->ch[0] == NULL)?0:root->ch[0]->siz;
pushdown(root);
splay(root->ch[1],b - 1 - s0);
}
void Add(int v) {
pushdown(root);
pushdown(root->ch[1]);
Node *x = root->ch[1]->ch[0];
if (x != NULL) {
x->add += v;
x->num += v;
x->ma += v;
}
}
void Rev() {
pushdown(root);
pushdown(root->ch[1]);
Node *x = root->ch[1]->ch[0];
if (x != NULL) x->rev ^= 1;
}
int Ans() {
return root->ch[1]->ch[0]->ma;
}
};
int n,m;
int main()
{
#ifdef YZY
freopen("yzy.txt","r",stdin);
#endif
static data tree;
cin >> n >> m;
for (int i = 1; i <= n+2; i++) tree.Ins(i);
while (m--) {
int k; scanf("%d",&k);
int L,R; scanf("%d%d",&L,&R);
tree.spl(L,R+2);
if (k == 1) {
int v;
scanf("%d",&v);
tree.Add(v);
}
else if (k == 2) {
tree.Rev();
}
else printf("%d\n",tree.Ans());
}
return 0;
}