BZOJ 2658 [Zjoi2012]小蓝的好友(mrx)

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

Time Limit: 20 Sec   Memory Limit: 128 MB
Submit: 386   Solved: 238
[ Submit][ Status][ Discuss]

Description

终于到达了这次选拔赛的最后一题,想必你已经厌倦了小蓝和小白的故事,为了回馈各位比赛选手,此题的主角是贯穿这次比赛的关键人物——小蓝的好友。
在帮小蓝确定了旅游路线后,小蓝的好友也不会浪费这个难得的暑假。与小蓝不同,小蓝的好友并不想将时间花在旅游上,而是盯上了最近发行的即时战略游戏——SangoCraft。但在前往通关之路的道路上,一个小游戏挡住了小蓝的好友的步伐。
“国家的战争其本质是抢夺资源的战争”是整款游戏的核心理念,这个小游戏也不例外。简单来说,用户需要在给定的长方形土地上选出一块子矩形,而系统随机生成了N个资源点,位于用户所选的长方形土地上的资源点越多,给予用户的奖励也越多。悲剧的是,小蓝的好友虽然拥有着极其优秀的能力,但同时也有着极差的RP,小蓝的好友所选的区域总是没有一个资源点。
终于有一天,小蓝的好友决定投诉这款游戏的制造厂商,为了搜集证据,小蓝的好友想算出至少包含一个资源点的区域的数量。作为小蓝的好友,这自然是你分内之事。
 

Input

 每个输入文件中仅包含一个测试数据。
第一行包含两个由空格隔开的正整数R,C,N,表示游戏在一块[1,R]X[1,C]的地图上生成了N个资源点。
     接下来有N行,每行包含两个整数 x,y,表示这个资源点的坐标
(1<=x<=R,1<=Y<=c)

Output

      输出文件应仅包含一个整数,表示至少包含一个资源点的区域的数量。具体的说,设N个资源点的坐标为(i=1..n),你需要计算有多少个四元组(LB,DB,RB,UB)满足1<=LB<=RB<=R,1<=DB<=UB<=C,且存在一个i使得
LB<=Xi<=RB,DB<=Yi<=UB
均成立

Sample Input

5 5 4
1 2
2 3
3 5
4 1

Sample Output

139

思路:全部子矩形的数量-空资源矩形的数量。,Treap打标记维护每一列向上延伸的距离来求空矩形的数量。

Point:
①如何求出全部数量:子矩形的确定可以靠对角线决定,那么我们就只需确定对角线的位置就可以,对角线又由
两个端点决定,端点由坐标决定,那么我们就需要两个x值和两个y值决定,就可以得出C(w+1,2)*C(h+1,2)【w为宽
,h为高】
②关于如何维护求空矩形的数量:http://wjmzbmr.com/archives/zjoi_2012_round_1_mrx_detailed_problem_solutions/
博客写的很清楚了,就不写了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls ch[p][0]
#define rs ch[p][1]
#define PI pair<int,int>
#define mp(a,b) make_pair(a,b)
#define fi first
#define se second
const int maxn=100010;
using namespace std;
typedef long long ll;
int n,m,P;PI poi[maxn];ll res;

struct Treap{
	int ch[maxn][2],add[maxn],size[maxn],h[maxn],root;
	ll ans[maxn];
	void inc(int p,int v){if (p) h[p]+=v,add[p]+=v;}
	void down(int p){
		if (add[p]){
			if (ls) inc(ls,add[p]);
			if (rs) inc(rs,add[p]);
			add[p]=0;
		}
	}
	void update(int p){
		size[p]=1,ans[p]=0;
		if (ls) size[p]+=size[ls],ans[p]+=ans[ls]+1ll*(h[ls]-h[p])*size[ls]*(size[ls]+1)/2;
		if (rs) size[p]+=size[rs],ans[p]+=ans[rs]+1ll*(h[rs]-h[p])*size[rs]*(size[rs]+1)/2;
	}
	int merge(int a,int b){
		if (!a){update(b);return b;}
		if (!b){update(a);return a;}
		down(a),down(b);
		if (h[a]<h[b]){ch[a][1]=merge(ch[a][1],b),update(a);return a;}
		else{ch[b][0]=merge(a,ch[b][0]),update(b);return b;}
	}
	PI split(int p,int k){
		if (!p) return mp(0,0);
		down(p);
		if (size[ls]+1<=k){
			PI tmp=split(rs,k-size[ls]-1);
			rs=tmp.first,update(p);
			return mp(p,tmp.second);
		}
		else{
			PI tmp=split(ls,k);
			ls=tmp.second,update(p);
			return mp(tmp.first,p);
		}
	}
	ll query(){
		down(root);
		return ans[root]+1ll*h[root]*size[root]*(size[root]+1)/2;
	}
	void work(){
		for (int i=1,j=1;i<=n;i++){
			inc(root,1);
			for (;poi[j].fi==i;j++){
				PI tmp1=split(root,poi[j].se-1),tmp2=split(tmp1.se,1);
				h[tmp2.fi]=0;
				root=merge(merge(tmp1.fi,tmp2.fi),tmp2.se);
			}
			res-=query();
		}
		printf("%lld\n",res);
	}
}T;

int main(){
	scanf("%d%d%d",&n,&m,&P);
	for (int i=1;i<=P;i++) scanf("%d%d",&poi[i].fi,&poi[i].se);
	sort(poi+1,poi+1+P);
	for (int i=1;i<=m;i++) T.root=T.merge(T.root,i);
	res=1ll*n*(n+1)/2*m*(m+1)/2;T.work();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值