bzoj2658: [Zjoi2012]小蓝的好友(mrx)

来源:互联网 发布:淘宝买洗衣机可靠吗 编辑:程序博客网 时间:2024/05/01 22:21

突然发现直接做zjoi貌似是不大可能的。。每题都不会啊。。

首先可以看一遍clj的题解,但其中并没有代码实现。据说clj写的是多叉树,但没找到代码,然后又看到了ydc的fhq式treap很短,就模仿他写了。‘

fhq式的treap(可持久化treap)可以参照他本人的博客和他的论文和clj的论文,都有提到这一点。但这题的treap有点不同,首先为每个列都创建一个点,按照中序遍历确定位置,然后每个点都有一个h值,代表多少高度内没有资源点。因为数据时随机生成的所以就能作为treap的随机变量(clj说能用笛卡尔树证明,不明觉厉,懂的人请教教我)。然后对每一行都求出以这行为底边的不含资源点的矩阵的个数。

参考资料:


1、clj详细题解(不让直接链接,用了个短网址) http://hi.baidu.com/wjbzbmr/item/5090883431bd981c9dc65edc

2、ydc大神

/**************************************************************    Problem: 2658    User: zhengly123    Language: C++    Result: Accepted    Time:1756 ms    Memory:16096 kb****************************************************************/ #include <stdlib.h>#include <stdio.h>#include <string.h>#include <iostream>#include <math.h>#include <algorithm>#define MEM(a) memset(a,1,sizeof(a))using namespace std; const int MAXN = 100010;const int MAXNODE = 400010;const int INF = 999999999;typedef pair<int, int> pa;struct node{    int size, h, lch, rch, detla;    long long s;}tr[MAXNODE];int root, r, c;inline void up(int c){    tr[c].size = 1 + tr[tr[c].lch].size + tr[tr[c].rch].size;    tr[c].s = (long long)tr[tr[c].lch].s + tr[tr[c].rch].s + (((long long)tr[tr[c].lch].h - tr[c].h)*tr[tr[c].lch].size*(tr[tr[c].lch].size + 1) >> 1);    tr[c].s += ((long long)tr[tr[c].rch].h - tr[c].h)*tr[tr[c].rch].size*(tr[tr[c].rch].size + 1) >> 1;} inline void down(int c){    if (!tr[c].detla) return;    if (tr[c].lch)    {        tr[tr[c].lch].h += tr[c].detla;        tr[tr[c].lch].detla += tr[c].detla;    }    if (tr[c].rch)    {        tr[tr[c].rch].h += tr[c].detla;        tr[tr[c].rch].detla += tr[c].detla;    }    tr[c].detla = 0;} pa split(int c, int w){    if (!c) return pa(0, 0);    down(c);    pa t;    if (tr[tr[c].lch].size + 1 <= w)    {        t = split(tr[c].rch, w - tr[tr[c].lch].size - 1);        tr[c].rch = t.first;        up(c);        return pa(c, t.second);    }    else    {        t = split(tr[c].lch, w);        tr[c].lch = t.second;        up(c);        return pa(t.first, c);    }} int merge(int t1, int t2){    if (!t1 || !t2) return t1 ? t1 : t2;    if (!t1){ up(t2); return t2; }    if (!tr){ up(t1); return t1; }    down(t1), down(t2);    if (tr[t1].h < tr[t2].h)    {        tr[t1].rch = merge(tr[t1].rch, t2);        up(t1);        return t1;    }    else    {        tr[t2].lch = merge(t1, tr[t2].lch);        up(t2);        return t2;    }} struct point{ int x, y; }p[MAXN]; bool cmp(const point &a, const point &b) { return a.x < b.x; } void work(){    int i, j = 1, n;    pa t1, t2;    scanf("%d%d%d", &r, &c, &n);    long long ans = (long long)r*(r + 1)*c*(c + 1) >> 2;    for (i = 1; i <= n; ++i) scanf("%d%d", &p[i].x, &p[i].y);    sort(p + 1, p + 1 + n, cmp);    for (i = 1; i <= c; ++i)    {        root = merge(root, i);        up(root);    }    for (i = 1; i <= r; ++i)    {        tr[root].h += 1;        tr[root].detla += 1;        if (i == 40000)        {            i += 0;        }        while (p[j].x == i)        {            t1 = split(root, p[j].y - 1);            t2 = split(t1.second, 1);            tr[t2.first].h = 0;            root = merge(t1.first, t2.first);            root = merge(root, t2.second);            ++j;        }        ans -= (long long)tr[root].s + (((long long)tr[root].h*tr[root].size*(tr[root].size + 1)) >> 1);//位运算的优先级很坑,一定要加括号    }    cout << ans;}int main(){    work();    return 0;}


0 0
原创粉丝点击