【BZOJ2658】[Zjoi2012]小蓝的好友(mrx) 平衡树维护笛卡尔树+扫描线
【BZOJ2658】[Zjoi2012]小蓝的好友(mrx)
Description
Input
Output
Sample Input
1 2
2 3
3 5
4 1
Sample Output
HINT
【数据范围】
对于100%的数据,R,C<=40000,N<=100000,资源点的位置两两不同,且位置为随机生成。
题解:第一思路一定是补集转化,我们改求不包含黑点的矩形个数。然后考虑枚举矩形的底边所在行,考虑这一行的贡献是什么。
我们将这一行中,每一列上面遇到的第一个黑点到这一行的距离定义为这一列的高度。然后我们对这一行中,所有列的高度建出一棵笛卡尔树。假设树上第i个节点的子树大小是siz[i],高度是h[i],那么这个点对答案的贡献就是${siz\times (siz+1) \over 2}\times(h[i]-h[fa])$。
这样做的复杂度是O(Rn)的。但是我们发现数据是随机的,随机数据有什么性质?随机序列的笛卡尔树的树高是O(logn)的,并且笛卡尔树其实是一棵Treap!所以我们可以考虑用Treap维护笛卡尔树。当我们向下平移一行时,首先所有点的高度+1,这个打标记就好;然后这一行可能冒出来一些黑点,我们将这些黑点旋转上来,然后将高度变成0即可。我们还要动态维护一下所有点的${siz\times (siz+1) \over 2}\times(h[i]-h[fa])$,这个比较麻烦,需要注意一下细节。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int maxn=100010;
typedef long long ll;
vector<int> px[maxn];
vector<int>::iterator it;
ll ans;
int R,C,n,rt;
struct node
{
int ch[2],siz,fa,h,tag;
ll sum;
}s[maxn];
inline ll c(const ll &x) {return x*(x+1)>>1;}
inline void add(int x,int y) {s[x].h+=y,s[x].tag+=y;}
inline void pushdown(int x)
{
if(s[x].tag)
{
if(s[x].ch[0]) add(s[x].ch[0],s[x].tag);
if(s[x].ch[1]) add(s[x].ch[1],s[x].tag);
s[x].tag=0;
}
}
inline void pushup(int x)
{
s[x].siz=s[s[x].ch[0]].siz+s[s[x].ch[1]].siz+1;
s[x].sum=s[s[x].ch[0]].sum+s[s[x].ch[1]].sum+c(s[x].siz)*(s[x].h-s[s[x].fa].h);
}
void updata(int x)
{
if(x!=rt) updata(s[x].fa);
pushdown(x);
}
inline void rotate(int x)
{
int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]);
if(y==rt) rt=x;
else s[z].ch[y==s[z].ch[1]]=x;
s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1];
if(s[x].ch[d^1]) s[s[x].ch[d^1]].fa=y,pushdown(s[x].ch[d^1]),pushup(s[x].ch[d^1]);
s[x].ch[d^1]=y;
pushup(y),pushup(x);
}
int build(int l,int r)
{
if(l>r) return 0;
int x=(l+r)>>1;
s[x].ch[0]=build(l,x-1),s[x].ch[1]=build(x+1,r),s[x].siz=r-l+1;
if(s[x].ch[0]) s[s[x].ch[0]].fa=x;
if(s[x].ch[1]) s[s[x].ch[1]].fa=x;
return x;
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
int main()
{
R=rd(),C=rd(),n=rd();
int i,a,b;
for(i=1;i<=n;i++) a=rd(),b=rd(),px[b].push_back(a);
rt=build(1,R);
for(i=C;i>=1;i--)
{
add(rt,1),pushup(rt);
for(it=px[i].begin();it!=px[i].end();it++)
{
a=*it,updata(a);
while(a!=rt) rotate(a);
s[a].h=0;
if(s[a].ch[0]) pushdown(s[a].ch[0]),pushup(s[a].ch[0]);
if(s[a].ch[1]) pushdown(s[a].ch[1]),pushup(s[a].ch[1]);
pushup(a);
}
ans+=s[rt].sum;
}
printf("%lld",c(R)*c(C)-ans);
return 0;
}
【BZOJ2658】[Zjoi2012]小蓝的好友(mrx) 平衡树维护笛卡尔树+扫描线的更多相关文章
- bzoj2658: [Zjoi2012]小蓝的好友(mrx)
太神辣 treap的随机键值竟然能派上用场.. 要用不旋转的treap来进行维护区间信息 #include<cstdio> #include<cstring> #include ...
- 【BZOJ2658】[Zjoi2012]小蓝的好友(mrx) (扫描线,平衡树,模拟)
题面 终于到达了这次选拔赛的最后一题,想必你已经厌倦了小蓝和小白的故事,为了回馈各位比赛选手,此题的主角是贯穿这次比赛的关键人物--小蓝的好友. 在帮小蓝确定了旅游路线后,小蓝的好友也不会浪费这个难得 ...
- @bzoj - 2658@ [Zjoi2012]小蓝的好友(mrx)
目录 @description@ @solution@ @accepted code@ @details@ @description@ 终于到达了这次选拔赛的最后一题,想必你已经厌倦了小蓝和小白的故事 ...
- BZOJ2658 ZJOI2012 小蓝的好友(treap)
显然转化为求不包含关键点的矩形个数.考虑暴力,枚举矩形下边界,求出该行每个位置对应的最低障碍点高度,对其建笛卡尔树,答案即为Σhi*(slson+1)*(srson+1),即考虑跨过该位置的矩形个数. ...
- 平衡树及笛卡尔树讲解(旋转treap,非旋转treap,splay,替罪羊树及可持久化)
在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用 ...
- 洛谷 P2611 [ZJOI2012]小蓝的好友 解题报告
P2611 [ZJOI2012]小蓝的好友 题目描述 终于到达了这次选拔赛的最后一题,想必你已经厌倦了小蓝和小白的故事,为了回馈各位比赛选手,此题的主角是贯穿这次比赛的关键人物--小蓝的好友. 在帮小 ...
- [ZJOI2012]小蓝的好友
https://www.luogu.org/problemnew/show/P2611 题解 \(n\times m\)肯定过不去.. 我们把给定的点看做障碍点,考虑先补集转化为求全空矩阵. 然后我们 ...
- ☆ [ZJOI2006] 书架 「平衡树维护数列」
题目类型:平衡树 传送门:>Here< 题意:要求维护一个数列,支持:将某个元素置顶或置底,交换某元素与其前驱或后继的位置,查询编号为\(S\)的元素的排名,查询排名第\(k\)的元素编号 ...
- BZOJ 1014 火星人 | 平衡树维护哈希
BZOJ 1014 火星人 题意 有一个字符串,三中操作:在某位置后面插入一个字符.修改某位置的字符.询问两个后缀的最长公共前缀. 题解 看到网上的dalao们都说这道题是平衡树,我就很懵x--平衡树 ...
随机推荐
- Objective-C 语法之 Debug 表达式
main.m #import <Foundation/Foundation.h> #import "TestClass.h" int main(int argc, co ...
- 生成asm-offset
因为不善于在Makefile中调用shell的相关工具,所以关于asm-offsets.h中的产生的16进制数并不知如何做到. 因此自己写了个脚本,可以生成同样的文件(再次造了轮子). 参考:http ...
- Eclipse + PyDev 快捷键
●多行缩进(减少缩进):tab/shift+tab ●复制行: Ctrl+Alt+方向键'↓' ●删除行:Ctrl+d ●自动完成:Alt+/ ●注释:Ctrl+/ ●窗口最大小:Ctrl+m == ...
- 简要介绍DES、RSA MD5 sha1 四种加密算法的优缺点,以及使用场合
美国数据加密标准(DES)是对称密码算法,就是加密密钥能够从解密密钥中推算出来,反过来也成立.密钥较短,加密处理简单,加解密速度快,适用于加密大量数据的场合.RSA是非对称算法,加密密钥和解密密钥是不 ...
- 如何用BarTender 2016字处理器完成表格设计
很多时候,需要应客户要求,用BarTender 2016设计带表格的标签.在BarTender 2016中字处理器文本对象可以使用字处理中的诸多格式功能(如项目符号.编号列表.表格.混合字体以及RTF ...
- flashfxp v3.7 注册码
-------- FlashFXP Registration Data START --------FLASHFXPvwBW1S4QvwAAAAC5W5MNJwXnsl73i3CxcVAAvAyagF ...
- 如果你的eclipse在每次run或debug时都莫名其妙的做一件事
新项目,使用Ant打war包.结果写完了Ant以后,包是打好了,却使eclipse以后每次run或debug时都莫名其妙地自动先执行这个Ant, 让人十分苦恼. 其实,是你的eclipse设置出了问题 ...
- 完美解决ListView中事件ItemCreated中使用ClientID导致插入数据失败
于昨天晚上看到视频做到这个例子,但是发现始终有错误,在ListView的ItemCreated事件中使用了ClientID则会导致数据插入数据库失败.当点击插入按钮时,网页就像点击F5刷新一样,无任何 ...
- 【笔试面试】神马搜索C++程序猿电话面试
面试时间:2015.07.15 预约时间:2015.07.14.电话面试前一天,会电话咨询你方面电话面试的时间. 面试环节: 无自我介绍(这是我面试这么多家公司碰到的第一次),直接面试内容. 问题1: ...
- Netty权威指南之伪异步I/O编程
为了解决同步阻塞I/O一个链路需要一个线程处理问题,对BIO模型做了优化——后端通过一个线程池处理多个客户端的请求接入,设置线程最大值,防止线程并发接入导致的线程耗尽. 当有新的客户端接入时,将客户端 ...