zoukankan      html  css  js  c++  java
  • 左偏树

    思想

    这是一种支持合并操作的堆,实现起来很简单

    对于每一个节点,拥有一个dis值,即到儿子的最短距离

    其具有左偏性质:左二子的dis值大于右儿子的dis值

    由于此性质,保证了合并的时间复杂度是o(logn)的

    每次合并时,沿着两个堆的右子树进行

    每次合并其中一个的右子树和另外一个堆

    代码

    #include<bits/stdc++.h>
    const int maxn=300000;
    int v[maxn],fa[maxn],left1[maxn],right1[maxn],dis[maxn],id,xx,yy,x,y,n,m;
    using namespace std;
    int getfa(int x)
    { 
      while (fa[x]!=0) x=fa[x];
        return(x);
    };
    int merge(int r1,int r2)
    {
        if (r1==0 or r2==0) return(r1+r2);
        if (v[r1]>v[r2] or v[r1]==v[r2] and r1>r2) swap(r1,r2);
        right1[r1]=merge(right1[r1],r2);
        fa[right1[r1]]=r1;
        if (dis[left1[r1]]<dis[right1[r1]]) swap(left1[r1],right1[r1]);
        dis[r1]=dis[right1[r1]]+1;
        return(r1);
    };
    void delete1(int r1)
    {
        v[r1]=-1;
        fa[left1[r1]]=0; fa[right1[r1]]=0;
        merge(left1[r1],right1[r1]);
    };
    int main(){
        freopen("noip.in","r",stdin);
        freopen("noip.out","w",stdout);
      cin>>n>>m;
      for (int i=1; i<=n; i++) cin>>v[i];
      for (int i=1; i<=m; i++){
          cin>>id;
          if (id==1) 
            {
            cin>>x>>y;
            if (v[x]==-1 or v[y]==-1) continue;
            xx=getfa(x); yy=getfa(y);
            if (xx!=yy) merge(xx,yy);
          } else
            {
            cin>>x;
                if (v[x]==-1) 
                {
                     cout<<"-1"<<endl;
                     continue; 
              }
              xx=getfa(x);
              cout<<v[xx]<<endl;
              delete1(xx);
          }
      }  
      return(0);
    } 
  • 相关阅读:
    static作用(修饰函数、局部变量、全局变量)(转)
    地弹
    开漏(open drain)和开集(open colletor)
    过冲、振铃,非单调性
    串扰(crosstalk)
    数字通信基本概念
    电源和地
    分布式系统与集总系统
    传输线及其特性阻抗
    MSP430G2553 Launchpad 硬件I2C驱动
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/7892913.html
Copyright © 2011-2022 走看看