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)