一、斜堆

斜堆是一种可以合并的堆

节点信息:

struct Node {
    int v;
    Node *ch[2];
};

主要利用merge函数

Node *merge(Node *x, Node *y) {
    if(!x) return y;
    if(!y) return x;
    if(x->v < y->v) swap(x, y);
    x->ch[1] = merge(x->ch[1], y);
    return swap(x->ch[0], x->ch[1]), x;
}

左偏树需要维护一个额外的信息,而斜堆每次强制swap(ch[0], ch[1]),以达到均摊$O(\log{n})$的效果

 

利用merge函数可以很容易地实现插入和删除

void ins(Node*& o, int x) {
    o = merge(o, new Node(x));
}
void del(Node*& o) {
    o = merge(o->ch[0], o->ch[1]);
}

 

另外地,堆相对与平衡树来说无法删除一个元素,但是如果能够定位到这个指针就可以删除这个元素了,方法是存储父亲(merge里要维护一下fa)

删除一个元素时可以这样

void del(Node*& o) {
    Node* p = o->fa;
    Node* r = merge(o->ch[0], o->ch[1]);
    r->fa = p;
    p->ch[p->ch[1] == o] = r;
}

 

当然,和其他树形结构一样,堆上也是可以维护tag的

加入maintain()函数和down()函数后就可以轻松实现这些功能,方法和其他树形结构类似

需要注意的是删除时要像自底向上的splay一样把从这个点到根的路径上的点都down()一遍,再调用del()函数

 

另外,由于堆高度是均摊$O(\log{n})$的,所以在处理集合信息时不需要额外的并查集,只需要每次暴力往上找到根来比较就能够做到$O(\log{n})$的复杂度了。

 

!!!

!!!我现在收回 高度并不是均摊$O(\log{n})$高度是可以很大的 是会被卡的!!!!

 

举一例带标记的题

 

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<string>
  7 
  8 using namespace std;
  9 
 10 void setIO(const string& a) {
 11     freopen((a+".in").c_str(), "r", stdin);
 12     freopen((a+".out").c_str(), "w", stdout);
 13 }
 14 
 15 typedef long long ll;
 16 const int N = 300000 + 10;
 17 
 18 struct Node* pis;
 19 struct Node {
 20     ll v, a, m;
 21     int id, fk, tag;
 22     Node* ch[2];
 23     
 24     void add_tag(ll add, ll mul, int ft) {
 25         if(this) {
 26             fk += ft;
 27             tag += ft;
 28             (v *= mul) += add;
 29             m *= mul;
 30             (a *= mul) += add;
 31         }
 32     }
 33     
 34     void down() {
 35         ch[0]->add_tag(a, m, tag);
 36         ch[1]->add_tag(a, m, tag);
 37         tag = a = 0, m = 1;
 38     }
 39     
 40     void *operator new(size_t) {
 41         return pis++;
 42     }
 43     
 44     Node(ll v = 0, int id = 0) : v(v), id(id) {
 45         ch[0] = ch[1] = 0;
 46         a = 0;
 47         m = 1;
 48         fk = tag = 0;
 49     }
 50 }pool[N], *root[N];
 51 
 52 Node *merge(Node *l, Node *r) {
 53     if(!l || !r) return l ? l : r;
 54     if(l->v > r->v) swap(l, r);
 55     l->down();
 56     l->ch[1] = merge(l->ch[1], r);
 57     return swap(l->ch[0], l->ch[1]), l;
 58 }
 59 
 60 ll h[N], f[N], a[N], v[N];
 61 int ansn[N], ansm[N];
 62 
 63 template<typename Q> void gt(Q& x) {
 64     static char c;
 65     static bool f;
 66     for(f = 0; c = getchar(), !isdigit(c); ) if(c == '-') f = 1;
 67     for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - '0';
 68     if(f) x = -x;
 69 }
 70 
 71 void ddd(Node* o) {
 72     if(!o) return;
 73     o->down();
 74     ddd(o->ch[0]);
 75     ddd(o->ch[1]);
 76 }
 77 
 78 int main() {
 79 #ifdef DEBUG
 80     freopen("in.txt", "r", stdin);
 81     freopen("out.txt", "w", stdout);
 82 #endif
 83     
 84     pis = pool;
 85     int n, m;
 86     gt(n), gt(m);
 87     for(int i = 1; i <= n; i++) {
 88         gt(h[i]);
 89     }
 90     for(int i = 2; i <= n; i++) {
 91         gt(f[i]), gt(a[i]), gt(v[i]);
 92     }
 93     for(int i = 1; i <= m; i++) {
 94         ll s, c;
 95         gt(s), gt(c);
 96         root[c] = merge(root[c], new Node(s, i));
 97     }
 98     
 99     for(int i = n; i >= 1; i--) {
100         Node*& r = root[i];
101         while(r && r->v < h[i]) {
102             ansn[i]++;
103             r->down(); 
104             r = merge(r->ch[0], r->ch[1]);
105         }
106         ll add = 0, mul = 1;
107         if(a[i] == 0) add += v[i];
108         else mul *= v[i];
109         r->add_tag(add, mul, 1);
110         root[f[i]] = merge(root[f[i]], r);
111     }
112     
113     for(int i = 1; i <= n; i++) {
114         printf("%d\n", ansn[i]);
115     }
116     ddd(root[0]);
117     for(int i = 0; i < m; i++) {
118         ansm[pool[i].id] = pool[i].fk;
119     }
120     for(int i = 1; i <= m; i++) {
121         printf("%d\n", ansm[i]);
122     }
123     
124     return 0;
125 }
bzoj4003

相关文章:

  • 2021-12-28
  • 2021-07-19
  • 2022-03-09
  • 2021-10-04
  • 2021-07-26
  • 2021-06-04
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-09-12
  • 2021-07-26
  • 2022-02-14
  • 2022-01-13
相关资源
相似解决方案