zoukankan      html  css  js  c++  java
  • bzoj2658: [Zjoi2012]小蓝的好友(mrx)

    传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2658

    思路:显然答案=总矩形数-没有点的矩形数

    然后可以考虑用扫描线,现在只计算边界在这条线上的举行书,对每个点记录一个高度h[i],表示这条线上的这个点能走多远。

    因为数据随机,所以我们可以用h[i]当treap的键值,至于平衡树的值,自然就是位置了。

    然后我们就可以根据h划分出很多大矩形,对于一个高度为h,宽度为w的大矩形,增加的矩形数就是h*w*(w+1)/2,在treap里维护子节点的答案。

    维护的话,就是遇到一个点,就在treap里把h设为0,每做一行,root的h+1;


    具体可以看陈老师的题解: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
    ",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;
    }


  • 相关阅读:
    FZU 2150 Fire Game
    POJ 3414 Pots
    POJ 3087 Shuffle'm Up
    POJ 3126 Prime Path
    POJ 1426 Find The Multiple
    POJ 3278 Catch That Cow
    字符数组
    HDU 1238 Substing
    欧几里德和扩展欧几里德详解 以及例题CodeForces 7C
    Codeforces 591B Rebranding
  • 原文地址:https://www.cnblogs.com/thythy/p/5493529.html
Copyright © 2011-2022 走看看