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

太神辣 treap的随机键值竟然能派上用场。。

要用不旋转的treap来进行维护区间信息

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 #include<iostream>
  6
  7 using namespace std;
  8
  9 template<typename Q> Q &read(Q &x) {
 10     static char c, f;
 11     for(f = 0; c = getchar(), !isdigit(c); ) if(c == ‘-‘) f = 1;
 12     for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - ‘0‘;
 13     if(f) x = -x; return x;
 14 }
 15 template<typename Q> Q read() {
 16     static Q x; read(x); return x;
 17 }
 18
 19 typedef long long LL;
 20 const int N = 40000 + 10;
 21
 22 LL S(LL x) {
 23     return x * (x + 1) >> 1;
 24 }
 25
 26 struct Node *null, *pis;
 27 struct Node {
 28     int sz, h, tag;
 29     LL ans;
 30     Node *ch[2];
 31
 32     Node() {}
 33     Node(int h) : h(h) {
 34         sz = 1, ans = tag = 0;
 35         ch[0] = ch[1] = null;
 36     }
 37
 38     void add(int d) {
 39         if(this == null) return;
 40         h += d, tag += d;
 41     }
 42
 43     void maintain() {
 44         sz = ch[0]->sz + ch[1]->sz + 1;
 45         ans = 0;
 46         for(int c = 0; c < 2; c++) {
 47             ans += ch[c]->ans + S(ch[c]->sz) * (ch[c]->h - h);
 48         }
 49     }
 50
 51     void down() {
 52         ch[0]->add(tag);
 53         ch[1]->add(tag);
 54         tag = 0;
 55     }
 56
 57     void *operator new(size_t) {
 58         return pis++;
 59     }
 60 }pool[N];
 61
 62 Node *merge(Node *l, Node *r) {
 63     if(l == null) return r;
 64     if(r == null) return l;
 65     if(l->h < r->h) {
 66         l->down();
 67         l->ch[1] = merge(l->ch[1], r);
 68         return l->maintain(), l;
 69     }else {
 70         r->down();
 71         r->ch[0] = merge(l, r->ch[0]);
 72         return r->maintain(), r;
 73     }
 74 }
 75
 76 typedef pair<Node *, Node *> pnn;
 77 pnn split(Node *o, int k) {
 78     if(o == null) return pnn(null, null);
 79     pnn res; o->down();
 80     if(o->ch[0]->sz >= k) {
 81         res = split(o->ch[0], k);
 82         o->ch[0] = res.second;
 83         res.second = o;
 84     }else {
 85         res = split(o->ch[1], k - o->ch[0]->sz - 1);
 86         o->ch[1] = res.first;
 87         res.first = o;
 88     }
 89     return o->maintain(), res;
 90 }
 91
 92 pair<int, int> p[100000 + 10];
 93
 94 int main() {
 95 #ifdef DEBUG
 96     freopen("in.txt", "r", stdin);
 97     freopen("out.txt", "w", stdout);
 98 #endif
 99
100     int r, c, n;
101     scanf("%d%d%d", &r, &c, &n);
102     for(int i = 0; i < n; i++) {
103         scanf("%d%d", &p[i].first, &p[i].second);
104     }
105     sort(p, p + n);
106
107     pis = pool, null = new Node(0);
108     null->sz = 0;
109     Node *root = null;
110     for(int i = 1; i <= c; i++) {
111         root = merge(root, new Node(0));
112     }
113
114     LL ans = S(r) * S(c);
115     for(int i = 1, j = 0; i <= r; i++) {
116         root->add(1);
117         while(j < n && p[j].first == i) {
118             int x = p[j++].second;
119             pnn r1 = split(root, x - 1);
120             pnn r2 = split(r1.second, 1);
121             r2.first->h = 0;
122             root = merge(merge(r1.first, r2.first), r2.second);
123         }
124         ans -= root->ans + S(root->sz) * root->h;
125     }
126     cout << ans << endl;
127
128     return 0;
129 }

时间: 2024-08-25 09:55:51

bzoj2658: [Zjoi2012]小蓝的好友(mrx)的相关文章

[ZJOI2012]小蓝的好友

https://www.luogu.org/problemnew/show/P2611 题解 \(n\times m\)肯定过不去.. 我们把给定的点看做障碍点,考虑先补集转化为求全空矩阵. 然后我们枚举每一行,令这一行每个点的权值为从这点向上的极大不包含障碍点的连续段. 然后对这个序列建立笛卡尔树,那么答案为: \[ f[x]=(h[x]-h[fa[x]])*\frac{szie[x]*(size[x]+1)}{2} \] 我们的笛卡尔树上的的每个节点都要维护一个这样的信息. 现在我们还需要扫

【ZJOI2012】小蓝的好友 - 题解

题目链接 [ZJOI2012]小蓝的好友 做法 至少包含一个点的矩阵数等于总矩阵数减去不包含任意一个点的矩阵数. 考虑将点按照纵坐标排序,进行类似扫描线的操作.每一列有用的点是最靠近当前行的点,记录它们的纵坐标.如果这一层存在一段长度为 $ s $ 不包含点,则它对答案的贡献为 $ \frac{(s + 1) \times s}{2} $ :如果是纵坐标上一段都满足,那就再乘上纵坐标上的长度. 维护一个 $ Treap $ ,$ value $ 值中序遍历表示横坐标的一段,$ key $ 值表示

BZOJ 2658 小蓝的好友

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2658 题意:给出一个n*m的格子.某些格子中有障碍.求包含至少一个障碍的矩形有多少个? 思路:我们求空白矩形的个数. 从上到下一行一行计算,每到达一行,计算以该行为底的空白矩形个数.我们只需要知道每列向上延伸的最大距离. 这个可以看做是一棵树 我们只需要记录每个的高度即可. 那么每次增加一行,若整行都没有障碍,则根节点的高度增加1.否则,障碍将树分为若干子树.这个操作可以用fhq

【BZOJ 2656】2656: [Zjoi2012]数列(sequence) (高精度)

2656: [Zjoi2012]数列(sequence) Time Limit: 2 Sec  Memory Limit: 128 MBSubmit: 1499  Solved: 786 Description 小白和小蓝在一起上数学课,下课后老师留了一道作业,求下面这个数列的通项公式: 小白作为一个数学爱好者,很快就计算出了这个数列的通项公式.于是,小白告诉小蓝自己已经做出来了,但为了防止小蓝抄作业,小白并不想把公式公布出来.于是小白为了向小蓝证明自己的确做出来了此题以达到其炫耀的目的,想出了

【BZOJ2656】 [Zjoi2012]数列(sequence)

2656: [Zjoi2012]数列(sequence) Time Limit: 2 Sec  Memory Limit: 128 MBSubmit: 1485  Solved: 779[Submit][Status][Discuss] Description 小白和小蓝在一起上数学课,下课后老师留了一道作业,求下面这个数列的通项公式: 小白作为一个数学爱好者,很快就计算出了这个数列的通项公式.于是,小白告诉小蓝自己已经做出来了,但为了防止小蓝抄作业,小白并不想把公式公布出来.于是小白为了向小蓝

bzoj 2656 [Zjoi2012]数列(sequence) 递推+高精度

2656: [Zjoi2012]数列(sequence) Time Limit: 2 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 小白和小蓝在一起上数学课,下课后老师留了一道作业,求下面这个数列的通项公式: 小白作为一个数学爱好者,很快就计算出了这个数列的通项公式.于是,小白告诉小蓝自己已经做出来了,但为了防止小蓝抄作业,小白并不想把公式公布出来.于是小白为了向小蓝证明自己的确做出来了此题以达到其炫耀的目的,想出了

BZOJ-2657: [Zjoi2012]旅游(journey) (树形DP求最长链)

2657: [Zjoi2012]旅游(journey) Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1037  Solved: 655[Submit][Status][Discuss] Description 到了难得的暑假,为了庆祝小白在数学考试中取得的优异成绩,小蓝决定带小白出去旅游~~ 经过一番抉择,两人决定将T国作为他们的目的地.T国的国土可以用一个凸N边形来表示,N个顶点表示N个入境/出境口.T国包含N-2个城市,每个城市都是顶点均为N

【BZOJ2656】[Zjoi2012]数列(sequence) 高精度

[BZOJ2656][Zjoi2012]数列(sequence) Description 小白和小蓝在一起上数学课,下课后老师留了一道作业,求下面这个数列的通项公式: 小白作为一个数学爱好者,很快就计算出了这个数列的通项公式.于是,小白告诉小蓝自己已经做出来了,但为了防止小蓝抄作业,小白并不想把公式公布出来.于是小白为了向小蓝证明自己的确做出来了此题以达到其炫耀的目的,想出了一个绝妙的方法:即让小蓝说一个正整数N,小白则说出 的值,如果当N很大时小白仍能很快的说出正确答案,这就说明小白的确得到了

(树形DP) bzoj 2657

2657: [Zjoi2012]旅游(journey) Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 604  Solved: 387[Submit][Status][Discuss] Description 到了难得的暑假,为了庆祝小白在数学考试中取得的优异成绩,小蓝决定带小白出去旅游~~ 经过一番抉择,两人决定将T国作为他们的目的地.T国的国土可以用一个凸N边形来表示,N个顶点表示N个入境/出境口.T国包含N-2个城市,每个城市都是顶点均为N边