SuperMemo Treap
典型的区间操作水题, 我们要注意的点是REVOLVE操作中的T可能是负数.
我因为modify函数写错了, WA了好几次, 要细心.
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
long long inf = 0x3f3f3f3f3f3f3f3f;
const long long INF = inf << 1;
struct Treap;
Treap * null;
struct Treap{
Treap * left, * right;
long long value, minv, add;
int priority, rev, size;
Treap(){
add = 0;
rev = 0;
size = 0;
value = 0;
minv = INF;
}
Treap(Treap * l, Treap * r, long long v): left(l), right(r), value(v){
priority = rand();
rev = 0;
add = 0;
size = 1;
minv = value;
}
void modify(long long v){
if(this == null){
return;
}
add += v;
minv += v;
value += v;
}
void reverse(){
if(this == null){
return;
}
swap(left, right);
rev ^= 1;
}
void update(){
size = left->size + 1 + right->size;
minv = min(value, min(left->minv, right->minv));
}
void spread(){
if(this == null){
return;
}
if(add){
left->modify(add);
right->modify(add);
add = 0;
}
if(rev){
left->reverse();
right->reverse();
rev = 0;
}
}
};
void print(Treap * root){
if(root == null){
return;
}
root->spread();
print(root->left);
// printf(" %lld ", root->value);
cout << " " << root->value << " " << endl;
print(root->right);
}
void ppp(Treap * root, string inf){
print(root);
cout << string("\t") << inf << endl << endl;
}
typedef pair<Treap *, Treap *> pTT;
pTT split(Treap * root, int k){
if(root == null){
return make_pair(null, null);
}
root->spread();
pTT result;
if(k <= root->left->size){
result = split(root->left, k);
root->left = result.second;
root->update();
result.second = root;
}
else{
result = split(root->right, k - root->left->size - 1);
root->right = result.first;
root->update();
result.first = root;
}
return result;
}
Treap * merge(Treap * left, Treap * right){
left->spread(), right->spread();
if(left == null){
return right;
}
if(right == null){
return left;
}
if(left->priority < right->priority){
left->right = merge(left->right, right);
left->update();
return left;
}
else{
right->left = merge(left, right->left);
right->update();
return right;
}
}
Treap * build(int n){
stack<Treap *> s;
long long num;
Treap * t, * last;
for(int i = 0; i < n; ++i){
cin >> num;
t = new Treap(null, null, num);
last = null;
while(s.size() && s.top()->priority > t->priority){
s.top()->update();
last = s.top();
s.pop();
}
if(s.size()){
s.top()->right = t;
}
s.push(t);
t->left = last;
}
while(s.size() > 1){
s.top()->update();
s.pop();
}
s.top()->update();
return s.top();
}
int main(){
ios::sync_with_stdio(false);
null = new Treap();
int n;
cin >> n;
Treap * work = build(n);
// ppp(work, "Build Finished");
int m, x, y, T;
long long P, D;
cin >> m;
string cmd;
while(m--){
cin >> cmd;
if(cmd == "ADD"){
cin >> x >> y >> D;
pTT left = split(work, x - 1);
pTT right = split(left.second, y - x + 1);
right.first->modify(D);
work = merge(left.first, merge(right.first, right.second));
}
else if(cmd == "REVERSE"){
cin >> x >> y;
pTT left = split(work, x - 1);
pTT right = split(left.second, y - x + 1);
right.first->reverse();
work = merge(left.first, merge(right.first, right.second));
}
else if(cmd == "REVOLVE"){
cin >> x >> y >> T;
T %= y - x + 1;
T += y - x + 1;
T %= y - x + 1;
pTT left = split(work, x - 1);
pTT right = split(left.second, y - x + 1);
pTT middle = split(right.first, y - x + 1 - T);
right.first = merge(middle.second, middle.first);
work = merge(left.first, merge(right.first, right.second));
}
else if(cmd == "INSERT"){
cin >> x >> P;
Treap * t = new Treap(null, null, P);
pTT result = split(work, x);
work = merge(merge(result.first, t), result.second);
}
else if(cmd == "DELETE"){
cin >> x;
pTT right = split(work, x);
pTT left = split(right.first, x - 1);
work = merge(left.first, right.second);
}
else if(cmd == "MIN"){
cin >> x >> y;
pTT left = split(work, x - 1);
pTT right = split(left.second, y - x + 1);
cout << right.first->minv << endl;
work = merge(left.first, merge(right.first, right.second));
}
// ppp(work, "HAVE changed");
}
return 0;
}