zoukankan      html  css  js  c++  java
  • 配对堆学习笔记

    配对堆学习笔记

    可并堆,比较好写,不能持久化。

    结构是一个儿子指针一个兄弟指针,根链式前向星差不多。合并就直接把大的堆作为小的堆的儿子,删除就两两配对暴力合并儿子,这样好像可以让之后儿子数量少一点。具体的要用势能分析我也不会/kk

    例题:P3377

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int read(){
    	int x=0,pos=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    	return pos?x:-x;
    }
    #define ll long long
    #define FOR(i,a,b) for(int i=a;i<=b;i++)
    const int N = 1e5+200;
    int f[N];
    int gf(int x){
    	if(f[x]==x) return x;
    	else return f[x]=gf(f[x]); 
    }
    int nex[N],son[N];int cnt;ll val[N];
    void add(int u,int v){ //v作为u的儿子 
    	nex[v]=son[u];son[u]=v;
    } 
    int merge(int u,int v){//小根堆 
    	if(!u||!v) return u^v;
    	if(val[u]>val[v]||(val[u]==val[v]&&u>v)) swap(u,v);add(u,v);return u;
    }
    int merges(int u){//把u和u的兄弟两两配对,merge到一起 
    	if(!u) return 0; if(!nex[u]) return u;
    	int v1=nex[u],v2=nex[v1];
    	nex[u]=nex[v1]=0;return merge(merge(u,v1),merges(v2));
    } 
    /*
    void dfs(int u){
    	ans[++top]=val[u];
    	for(int i=son[u];i;i=nex[i]) dfs(i);
    }*/
    struct heap{
    	int rt;
    	void push(ll x){val[++cnt]=x;rt=merge(rt,cnt);}
    	ll top(){return val[rt];}
    	void pop(){rt=merges(son[rt]);}
    	void join(int now){rt=merge(rt,now);} 
    }h[N];
    int main(){
    	int n=read(),m=read();
    	FOR(i,1,n){
    		int x=read();f[i]=i;h[i].push(x);
    	}
    	FOR(i,1,m){
    		int opt=read();
    		if(opt==1){
    			int x=read(),y=read();int fu=gf(x),fv=gf(y);
    			if(val[x]==-1||val[y]==-1||fu==fv) continue;
    			f[fv]=fu;
    			h[fu].join(h[fv].rt); 
    		}else{
    			int x=read();
    			if(val[x]==-1) printf("-1
    ");
    			else{
    				int fu=gf(x);printf("%d
    ",h[fu].top());val[h[fu].rt]=-1;h[fu].pop();
    			}	
    		}
    	}
    	return 0;
    }
    

    例题 洛谷P3642 [APIO2016]烟火表演

    这题是维护凸包并,平移线段(插入拐点),弹出右端的一些线段

    由于斜率有规律,我们直接用可并堆维护拐点即可。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int read(){
    	int x=0,pos=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    	return pos?x:-x;
    }
    #define ll long long
    #define FOR(i,a,b) for(int i=a;i<=b;i++)
    #define ROF(i,a,b) for(int i=a;i>=b;--i)
    const int N = 6e6+200;
    int f[N];
    int gf(int x){
    	if(f[x]==x) return x;
    	else return f[x]=gf(f[x]); 
    }
    int nex[N],son[N],d[N];int cnt;ll val[N],w[N];
    void add(int u,int v){ //v作为u的儿子 
    	nex[v]=son[u];son[u]=v;
    } 
    int merge(int u,int v){//大根堆 
    	if(!u||!v) return u^v;
    	if(val[u]<val[v]) swap(u,v);add(u,v);return u;
    }
    int merges(int u){//把u和u的兄弟两两配对,merge到一起 
    	if(!u) return 0; if(!nex[u]) return u;
    	int v1=nex[u],v2=nex[v1];
    	nex[u]=nex[v1]=0;return merge(merge(u,v1),merges(v2));
    } 
    ll ans[N],top=0;
    void dfs(int u){
    	ans[++top]=val[u];
    	for(int i=son[u];i;i=nex[i]) dfs(i);
    }
    struct heap{
    	int rt;
    	void push(ll x){val[++cnt]=x;rt=merge(rt,cnt);}
    	ll top(){return val[rt];}
    	void pop(){rt=merges(son[rt]);}
    	void join(int now){rt=merge(rt,now);} 
    }h[N];
    int main(){
    	int n=read(),m=read(); 
    	ll s0=0;
    	FOR(i,2,n+m){
    		f[i]=read(),w[i]=read();d[f[i]]++;s0+=w[i];
    	}
    	ROF(i,n+m,2){
    		ll l=0,r=0;
    		while(d[i]){
    			d[i]--;r=h[i].top();h[i].pop();
    		}l=h[i].top();h[i].pop();
    		h[i].push(l+w[i]);h[i].push(r+w[i]);
    		h[f[i]].join(h[i].rt); 
    	}
    	dfs(h[1].rt);
    	sort(ans+1,ans+top+1);top-=d[1];
    	FOR(i,0,top-1){
    		s0-=1ll*(top-i)*(ans[i+1]-ans[i]);
    	}
    	printf("%lld
    ",s0);
    	return 0;
    }
    
  • 相关阅读:
    微信商城中使用微信支付接口获取用户地址
    微信支付开发流程
    沉默多年,重新开博
    Extjs 表单验证后,几种错误信息展示方式
    自己对Extjs的Xtemplate的忽略
    js execCommand
    支付宝支付
    C# 将短时间格式变长正常时间格式
    SortedDictionary
    sql操作
  • 原文地址:https://www.cnblogs.com/lcyfrog/p/14267391.html
Copyright © 2011-2022 走看看