Submission #9654662


Source Code Expand

Copy
#include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for(int i=0; i<(int)(n); i++)
#define DEBUG(x) cerr << #x << ": " << (x) << endl

namespace Tree234 {
    // no function
    using T = char;
    const T e = '\0';
    T f(T a, T b){
        return b;
    }

    // template begin
    struct Node;
    using Ptr = Node*;
    // using Ptr = shared_ptr<Node>;
    struct Node {
        int rank, size, cnt;
        Ptr ch[4];
        bool isLeaf() const {return cnt == 0;}
        bool is4Node() const {return cnt == 4;}
        T val;
        Node(T v=e):rank(0),size(1),ch{nullptr,nullptr,nullptr,nullptr},cnt(0),val(v){}
        Node(Ptr that){
            rank = that->rank; size = that->size; cnt = that->cnt;
            REP(i,cnt)ch[i] = that->ch[i];
            val = that->val;
        }
    };
    const int HIST_LIM = 8'000'000;
    const int HIST_REST = 50'000;
    Node pool[HIST_LIM + HIST_REST];
    int pool_tail = 0;
    Ptr newNode(T v=e){
        Ptr ret = &pool[pool_tail++];
        *ret = Node(v);
        return ret;
        // return make_shared<Node>(v,f);
    }
    Ptr newNode(Ptr node){
        Ptr ret = &pool[pool_tail++];
        *ret = Node(node);
        return ret;
        // return make_shared<Node>(node);
    }
    Ptr update(Ptr node){   // ephemeral
        if(node == nullptr)return nullptr;
        if(node->isLeaf())return node;
        node->rank = node->ch[0]->rank + 1;
        node->size = 0;
        node->val = e;
        REP(i,node->cnt){
            node->size += node->ch[i]->size;
            node->val = f(node->val, node->ch[i]->val);
        }
        return node;
    }
    void debug(Ptr node){
        if(node == nullptr){
            cerr << "-";
        }else if(node->isLeaf()){
            cerr << node->val;
        }else{
            cerr << "[" << node->val << "]";
            cerr << "(";
            REP(i,node->cnt){
                debug(node->ch[i]);
                cerr << ",";
            }
            cerr << ")";
        }
    }

    Ptr splitRoot(Ptr root){
        assert(root != nullptr && root->is4Node());
        Ptr ret = newNode(root);
        Ptr lft = newNode(), rgt = newNode();
        lft->cnt = rgt->cnt = 2;
        lft->ch[0] = ret->ch[0]; lft->ch[1] = ret->ch[1];
        rgt->ch[0] = ret->ch[2]; rgt->ch[1] = ret->ch[3];
        lft = update(lft); rgt = update(rgt);
        ret->cnt = 2;
        ret->ch[0] = lft; ret->ch[1] = rgt;
        return update(ret);
    }
    Ptr splitNode(Ptr node, int k){
        assert(node != nullptr && !node->is4Node() && k < node->cnt && node->ch[k] != nullptr && node->ch[k]->is4Node());
        node = newNode(node);
        Ptr lft = newNode(node->ch[k]);
        Ptr rgt = newNode();
        lft->cnt = rgt->cnt = 2;
        lft->ch[0] = lft->ch[0]; lft->ch[1] = lft->ch[1];
        rgt->ch[0] = lft->ch[2]; rgt->ch[1] = lft->ch[3];
        move_backward(node->ch + k+1, node->ch + node->cnt, node->ch + node->cnt + 1);
        node->cnt += 1;
        node->ch[k] = update(lft); node->ch[k+1] = update(rgt);
        return update(node);
    }
    Ptr _merge(Ptr lft, Ptr rgt, bool rev){
        assert(lft->rank > rgt->rank && !lft->is4Node());
        lft = newNode(lft);
        if(lft->rank == rgt->rank + 1){
            if(rev)move_backward(lft->ch, lft->ch + lft->cnt, lft->ch + lft->cnt + 1);
            lft->ch[!rev ? lft->cnt : 0] = rgt;
            lft->cnt += 1;
            return update(lft);
        }else{
            int k = !rev ? lft->cnt-1 : 0;
            if(lft->ch[k]->is4Node()){
                lft = splitNode(lft, k);
                k = !rev ? lft->cnt-1 : 0;
            }
            lft->ch[k] = _merge(lft->ch[k], rgt, rev);
            return update(lft);
        }
    }
    Ptr merge(Ptr lft, Ptr rgt){
        if(lft == nullptr)return rgt;
        if(rgt == nullptr)return lft;
        if(lft->rank == rgt->rank){
            Ptr ret = newNode();
            ret->cnt = 2;
            ret->ch[0] = lft; ret->ch[1] = rgt;
            return update(ret);
        }else{
            if(lft->rank > rgt->rank){
                if(lft->is4Node()){
                    lft = splitRoot(lft);
                }
                return _merge(lft, rgt, false);
            }else{
                if(rgt->is4Node()){
                    rgt = splitRoot(rgt);
                }
                return _merge(rgt, lft, true);
            }
        }
    }
    pair<Ptr,Ptr> split(Ptr node, int k){
        if(node == nullptr)return make_pair((Ptr)nullptr, (Ptr)nullptr);
        assert(k <= node->size);
        if(k==0){
            return make_pair((Ptr)nullptr, node);
        }else if(k == node->size){
            return make_pair(node, (Ptr)nullptr);
        }
        assert(!node->isLeaf());
        Ptr leftside = nullptr;
        Ptr rightside = nullptr;
        REP(to, node->cnt){
            int sz = node->ch[to]->size;
            if(k <= sz){
                pair<Ptr,Ptr> rec = split(node->ch[to], k);
                leftside = merge(leftside, rec.first);
                rightside = merge(rightside, rec.second);
                while(++to < node->cnt){
                    rightside = merge(rightside, node->ch[to]);
                }
                // free(node);
                return make_pair(leftside, rightside);
            }else{
                leftside = merge(leftside, node->ch[to]);
                k -= sz;
            }
        }
        assert(false);
    }
    Ptr insert(Ptr node, int k, T x){
        pair<Ptr,Ptr> P = split(node, k);
        Ptr nw = newNode(x);
        return merge(merge(P.first, nw), P.second);
    }
    Ptr erase(Ptr node, int k){
        pair<Ptr,Ptr> P1, P2;
        P1 = split(node, k);
        P2 = split(P1.second, 1);
        // free(P2.first);
        return merge(P1.first, P2.second);
    }
    T rangeGet(Ptr node, int l, int r){
        if(node == nullptr)return e;
        assert(0<=l && l<=r && r<=node->size);
        if(r-l == 0)return e;
        if(r-l == node->size)return node->val;
        assert(!node->isLeaf());
        T ret = e;
        REP(to, node->cnt){
            int sz = node->ch[to]->size;
            if(l<sz && r-l != 0){
                T chval;
                chval = rangeGet(node->ch[to], l, min(r, sz));
                ret = f(ret, chval);
            }
            l = max(0, l - sz); r = max(0, r - sz);
        }
        return ret;
    }
    T kth(Ptr node, int k){
        return rangeGet(node, k, k+1);
    }
    Ptr construct(T *arr, int n){
        vector<Ptr> v(n, nullptr);
        REP(i,n)v[i] = Tree234::newNode(arr[i]);
        while(v.size() > 1){
            if(v.size()%2 == 1)v.push_back(nullptr);
            int m = v.size();
            vector<Ptr> w(m/2, nullptr);
            REP(i,m/2){
                w[i] = Tree234::merge(v[2*i+0], v[2*i+1]);
            }
            swap(v, w);
        }
        return v[0];
    }
    // template end
};

// https://atcoder.jp/contests/joisc2012/tasks/joisc2012_copypaste
int m, q;
char s[1'252'830];
int main(){
    scanf("%d%s%d",&m,s,&q);
    int n = strlen(s);
    // initialize
    using Node = Tree234::Node;
    using Ptr = Tree234::Ptr;
    Ptr root = Tree234::construct(s, n);
    // query
    while(q--){
        int l,r,x;
        scanf("%d%d%d",&l,&r,&x);
        Ptr substr = Tree234::split(Tree234::split(root, r).first, l).second;
        pair<Ptr,Ptr> splitted = Tree234::split(root, x);
        root = Tree234::merge(Tree234::merge(splitted.first, substr), splitted.second);
        if(root->size > m){
            root = Tree234::split(root, m).first;
        }
        if(Tree234::pool_tail > Tree234::HIST_LIM){
            // reconstruct
            n = root->size;
            REP(i,n)s[i] = Tree234::kth(root, i);
            Tree234::pool_tail = 0;
            root = Tree234::construct(s, n);
        }
    }
    int sz = root->size;
    REP(i,sz)putchar(Tree234::kth(root, i));
    puts("");
    return 0;
}

Submission Info

Submission Time
Task copypaste - コピー&ペースト
User rickytheta
Language C++14 (GCC 5.4.1)
Score 100
Code Size 8221 Byte
Status
Exec Time 11263 ms
Memory 454196 KB

Compile Error

./Main.cpp: In function ‘int main()’:
./Main.cpp:223:28: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d%s%d",&m,s,&q);
                            ^
./Main.cpp:232:33: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d%d%d",&l,&r,&x);
                                 ^

Judge Result

Set Name Score / Max Score Test Cases
Set01 10 / 10 01-01, 01-02, 01-03, 01-04
Set02 10 / 10 02-01, 02-02, 02-03
Set03 10 / 10 03-01, 03-02, 03-03
Set04 10 / 10 04-01, 04-02
Set05 10 / 10 05-01, 05-02
Set06 10 / 10 06-01, 06-02
Set07 10 / 10 07-01, 07-02
Set08 10 / 10 08-01, 08-02
Set09 10 / 10 09-01, 09-02
Set10 10 / 10 10-01, 10-02, 10-03, 10-04
Case Name Status Exec Time Memory
01-01 568 ms 441728 KB
01-02 493 ms 441832 KB
01-03 133 ms 440576 KB
01-04 112 ms 440448 KB
02-01 1195 ms 443220 KB
02-02 1023 ms 443220 KB
02-03 1078 ms 443220 KB
03-01 1943 ms 444612 KB
03-02 1673 ms 444612 KB
03-03 1742 ms 444612 KB
04-01 2798 ms 445996 KB
04-02 2424 ms 445996 KB
05-01 3772 ms 447256 KB
05-02 3324 ms 447384 KB
06-01 4977 ms 448776 KB
06-02 4416 ms 448648 KB
07-01 6351 ms 450032 KB
07-02 5575 ms 450032 KB
08-01 7659 ms 451420 KB
08-02 7035 ms 451420 KB
09-01 9308 ms 452812 KB
09-02 8523 ms 452812 KB
10-01 11263 ms 454196 KB
10-02 10524 ms 454196 KB
10-03 10267 ms 454196 KB
10-04 7359 ms 454196 KB