Problem with persistent treap
Difference between en8 and en9, changed 20 character(s)
Hi community,↵

I'm big fan of treaps, but this task makes me feel stupid.↵
https://www.e-olymp.com/en/problems/2957↵

There is no English translate for some reason.↵
Task:↵
Given N single-element lists with integers 1..10^9, perform next queries:↵

- merge L R -> take two already exist lists and create a new one, equal concat(L,R)↵
- head L -> create two new lists: first contains first element of L, second — the rest of L.↵
- tail L -> create two new lists: first contains all L without last element, second — last element.↵

For every new list you need to output sum of it's elements.↵

I've did it with persistent treap — for every merge query: merge(root[L], root[R], root[++versions]),↵
for head — split(root[L], root[nextV()], root[nextV()], 1)↵
for tail — split(root[L], root[nextV()], root[nextV()], cnt[root[L]]-1);↵

But this fails 
with "Memory Limit" as for every query it creates at least Log new nodes ↵

~~~~~↵
typedef long long LL;↵
#define N 13000005↵
#define MOD 1000000007↵
int root[300005] , c;↵
struct Treap↵
{↵
    int sum[N];↵
    int nodecnt;↵
    int L[N] , R[N] , cnt[N];↵
    int key[N];↵
    void clear() {↵
        nodecnt = 0;↵
    }↵
    Treap () {clear();}↵
    bool hey(int A , int B) {↵
        return (LL)rand() * (cnt[A] + cnt[B]) < (LL)cnt[A] * RAND_MAX;↵
    }↵
    int newnode(int x) {↵
        ++ nodecnt , L[nodecnt] = R[nodecnt] = 0;↵
        cnt[nodecnt] = 1 , key[nodecnt] = x, sum[nodecnt] = x;↵
        return nodecnt;↵
    }↵
    int copynode(int A) {↵
        if (!A) return 0;↵
        ++ nodecnt , L[nodecnt] = L[A] , R[nodecnt] = R[A];↵
        cnt[nodecnt] = cnt[A] , key[nodecnt] = key[A], sum[nodecnt] = sum[A];↵
        if (nodecnt == 5000000 &mdash; 100) {↵
          printf("TREAP\n");↵
          exit(0);↵
        }↵
        return nodecnt;↵
    }↵
    void pushup(int x) {↵
        cnt[x] = 1;↵
        sum[x] = key[x];↵
        if (L[x]) {↵
          cnt[x] += cnt[L[x]];↵
          sum[x] = (sum[x] + sum[L[x]]) % MOD;↵
        }↵
        if (R[x]) {↵
          cnt[x] += cnt[R[x]];↵
          sum[x] = (sum[x] + sum[R[x]]) % MOD;↵
        }↵
    }↵
    void merge(int& p , int x , int y) {↵
        if (!x || !y) {↵
            p = 0;↵
            if (x) p = copynode(x);↵
            if (y) p = copynode(y);↵
        }↵
        else if ( hey(x , y) ) {↵
            p = copynode(x);↵
            merge(R[p] , R[x] , y) , pushup(p);↵
        }↵
        else {↵
            p = copynode(y);↵
            merge(L[p] , x , L[y]) , pushup(p);↵
        }↵
    }↵
    void split(int p , int& x , int& y , int size) {↵
        if (!size) {↵
             x = 0 , y = copynode(p);↵
             return;↵
        }↵
        if (cnt[L[p]] >= size) {↵
            y = copynode(p);↵
            split(L[p] , x , L[y] , size) , pushup(y);↵
        }↵
        else {↵
            x = copynode(p);↵
            split(R[p] , R[x] , y , size &mdash; cnt[L[p]] &mdash; 1) , pushup(x);↵
        }↵
    }↵
    void print(int p) {↵
        if (L[p]) print(L[p]);↵
        printf("%d ", key[p]);↵
        if (R[p]) print(R[p]);↵
    }↵
};↵
Treap T;↵
char s[10];↵

int main(void) {↵
  int n;↵
  scanf("%d", &n);↵
  int version = 0;↵
  REP(i, n) {↵
    int x;↵
    scanf("%d", &x);↵
    root[++version] = T.newnode(x);↵
  }↵

  int q;↵
  scanf("%d", &q);↵
  REP(i, q) {↵
    if (version >= 300005 &mdash; 50) {↵
      printf("TREAP2\n");↵
      exit(0);↵
    }↵
    scanf("%s", &s);↵
    if (s[0] == 'm') {↵
      int x,y;↵
      scanf("%d%d", &x, &y);↵
      T.merge(root[++version], root[x], root[y]);↵
      printf("%d\n", T.sum[root[version]]);↵
    }↵

    if (s[0] == 'h') {↵
      int x;↵
      scanf("%d", &x);↵
      int v1 = ++version;↵
      int v2 = ++version;↵
      T.split(root[x], root[v1], root[v2], 1);↵
      printf("%d\n%d\n", T.sum[root[v1]], T.sum[root[v2]]);↵
    }↵

    if (s[0] == 't') {↵
      int x;↵
      scanf("%d", &x);↵
      int v1 = ++version;↵
      int v2 = ++version;↵
      T.split(root[x], root[v1], root[v2], T.cnt[root[x]] - 1);↵
      printf("%d\n%d\n", T.sum[root[v1]], T.sum[root[v2]]);↵
    }↵
  }↵
}↵
~~~~~↵

Any ideas how to improve it?↵


History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en9 English stostap 2017-03-22 18:12:24 20 Tiny change: 'his fails as for ev' -> 'his fails with "Memory Limit" as for ev'
en8 English stostap 2017-03-22 16:29:51 0 (published)
en7 English stostap 2017-03-22 16:11:05 8 Tiny change: 'queries:\n- merge ' -> 'queries:\n\n- merge ' (saved to drafts)
en6 English stostap 2017-03-22 12:51:31 0 (published)
en5 English stostap 2017-03-22 12:51:16 3198
en4 English stostap 2017-03-22 12:50:55 3014
en3 English stostap 2017-03-22 12:50:30 151
en2 English stostap 2017-03-22 12:50:03 171 (saved to drafts)
en1 English stostap 2017-03-22 12:48:36 4337 Initial revision (published)