SuperMemo POJ3580 TREAP

21 篇文章 0 订阅
15 篇文章 0 订阅

SuperMemo Treap

POJ3580-SuperMemo

典型的区间操作水题, 我们要注意的点是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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值