【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--平衡树 ...
随机推荐
- Android四大组件之——Activity的开启:StartActivity()和StartActivityForResult()(图文详解)
如需转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai 联系方式:JohnTsai.Work@gmail.com ...
- yield 举例
示例代码: 神奇的地方在于yield返回的是一个IEumerable,可以直接枚举. // yield-example.cs using System; using System.Collection ...
- 放假前来个笑话:IT人士群聚喝酒的讲究(超级搞笑)
大家喝的是啤酒,这时你入座了…… 你给自己倒了杯可乐,这叫低配置. 你给自已倒了杯啤酒,这叫标准配置. 你给自己倒了杯茶水,这茶的颜色还跟啤酒一样,这叫木马. 你给自己倒了杯可乐,还滴了几滴醋,不仅颜 ...
- python使用tkinter写带界面的工具
python一般用来写纯脚本的居多,但也可以做有视图的产品出来,例如做网页和客户端工具.做成工具的好处是,让不懂代码的人也能使用,不需要去修改代码里面的参数,如果使用次数频繁,甚至比纯脚本跟节约时间: ...
- 8 -- 深入使用Spring -- 8...1 Spring提供的DAO支持
8.8.1 Spring提供的DAO支持. DAO模式是一种标准的Java EE设计模式,DAO模式的核心思想是,所有的数据库访问都通过DAO组件完成,DAO组件封装了数据库的增.删.查.改等原子操作 ...
- backbone学习笔记:集合(Collection)
集合(Collection)是一个Backbone对象,用来组织和管理多个模型,它不仅仅是一个javascript数组,还提供了专门的方法来对集合进行排序.过滤和遍历,集合可以方便的与REST服务器进 ...
- mongo数据库查询结果不包括_id字段方法
db.GPRS_PRODUCT_HIS_FEE.find({"条件字段" : "412171211145135"},{_id:0}) db.GPRS_PRODU ...
- HTML5和CSS3扁平化风格博客(基础篇)
多学一点总是好的~ 自始至终都觉得的css和html效果比较美观,于是在看慕课网教程时,自己也跟着敲了深爱着的前端代码 这部分分为两部分:①基础篇:http://www.imooc.com/learn ...
- 《Lua程序设计》第2章 类型与值 学习笔记
Lua中的8中基础类型:nil(空).boolean(布尔).number(数字).string(字符串).userdata(自定义类型).function(函数).thread(线程)和table( ...
- Struts2(五)数据校验
一.概述 在提交表单数据时,如果数据需要保存到数据库,空输入等可能会引发一些异常,为了避免引起用户的输入引起底层异常,通常在进行业务逻辑操作之前,先执行基本的数据校验. 下面通过两种方式来阐述Stru ...