BZOJ2658 ZJOI2012 小蓝的好友(treap)

  显然转化为求不包含关键点的矩形个数。考虑暴力,枚举矩形下边界,求出该行每个位置对应的最低障碍点高度,对其建笛卡尔树,答案即为Σhi*(slson+1)*(srson+1),即考虑跨过该位置的矩形个数。

  笛卡尔树就是treap,于是考虑利用treap将其动态维护,将hi设为treap的优先级。移动下边界,可以发现每次相当于将所有点的优先级+1,并对该行出现的关键点将对应位置的优先级设为0,打打标记瞎维护下即可。由于数据随机复杂度很对。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 100010
#define lson tree[k].ch[0]
#define rson tree[k].ch[1]
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,r,c,root,cnt;
ll ans;
struct data
{
	int x,y;
	bool operator <(const data&a) const
	{
		return x<a.x;
	}
}a[N];
struct data2{int ch[2],x,p,s,lazy;ll ans;
}tree[N<<1];
void up(int k)
{
	tree[k].s=tree[lson].s+tree[rson].s+1;
	tree[k].ans=tree[lson].ans+tree[rson].ans+1ll*tree[k].p*(tree[lson].s+1)*(tree[rson].s+1);
}
void move(int &k,int p)
{
	int t=tree[k].ch[p];
	tree[k].ch[p]=tree[t].ch[!p],tree[t].ch[!p]=k,up(k),up(t),k=t;
}
void build(int &k,int l,int r)
{
	if (l>r) return;
	k=++cnt;
	int mid=l+r>>1;
	tree[k].x=mid,tree[k].p=0;
	build(lson,l,mid-1);
	build(rson,mid+1,r);
	up(k);
}
void update(int k,int x)
{
	tree[k].lazy+=x;
	tree[k].p+=x;
	tree[k].ans+=1ll*x*tree[k].s*(tree[k].s+1)/2;
}
void down(int k)
{
	update(lson,tree[k].lazy);
	update(rson,tree[k].lazy);
	tree[k].lazy=0;
}
void modify(int &k,int x)
{
	down(k);
	if (tree[k].x==x) tree[k].p=0;
	else if (tree[k].x<x) modify(rson,x),move(k,1);
	else modify(lson,x),move(k,0);
	up(k);
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("bzoj2658.in","r",stdin);
	freopen("bzoj2658.out","w",stdout);
	const char LL[]="%I64d\n";
#else
	const char LL[]="%lld\n";
#endif
	r=read(),c=read(),n=read();
	for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();
	ans=1ll*r*(r+1)*c*(c+1)/4;
	sort(a+1,a+n+1);
	build(root,1,c);
	int x=0;
	for (int i=1;i<=r;i++)
	{
		update(root,1);
		while (a[x+1].x==i)
		{
			x++;
			modify(root,a[x].y);
		}
		ans-=tree[root].ans;
	}
	cout<<ans;
	return 0;
}
//ans=Σpi*(sl+1)*(sr+1)

 

  

 

posted @ 2019-03-29 23:45  Gloid  阅读(193)  评论(0编辑  收藏  举报