P1456 Monkey King 左偏树

  一开始有n只孤独的猴子,然后他们要打m次架,每次打架呢,都会拉上自己朋友最牛叉的出来跟别人打,打完之后战斗力就会减半,每次打完架就会成为朋友(正所谓不打不相识o(∩_∩)o )。问每次打完架之后那俩猴子最牛叉的朋友战斗力还有多少,若朋友打架就输出-1.

左偏树模板提 

主要麻烦的点在于 将最强的猴子能力减半以后下放到这颗子树的下面

注意什么时候该更新父节点  什么时候不该更新父节点

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
typedef pair<int,int>pii;
//////////////////////////////////
const int N=5e6+10;

int val[N],lson[N],rson[N],f[N],dis[N];
int find1(int x){return f[x]==x?x:f[x]=find1(f[x]);}

int Merge(int x,int y)
{
    if(!x||!y)return x+y;
    if(val[x]<val[y]||val[x]==val[y]&&x<y)swap(x,y);
    rson[x]=Merge(rson[x],y);
    if(dis[lson[x]]<dis[rson[x]])swap(lson[x],rson[x]);
    f[lson[x]]=f[rson[x]]=f[x]=x;
    dis[x]=dis[lson[x]]+1;
    return x;
}
void pop(int x){val[x]=-1;f[lson[x]]=lson[x];f[rson[x]]=rson[x];f[x]=Merge(lson[x],rson[x]);  }
int n,m,a,b;

int work(int a,int b)
{
    int x=find1(a),y=find1(b),root;
    if(x==y)return -1;

    val[x]/=2;
    root=Merge(lson[x],rson[x]);
    dis[x]=lson[x]=rson[x]=0;
    root=Merge(x,root);
    f[root]=f[x]=root;//该树的所有结点都连在x上

    val[y]/=2;
    root=Merge(lson[y],rson[y]);
    dis[y]=lson[y]=rson[y]=0;
    root=Merge(y,root);
    f[root]=f[y]=root;

    root=Merge(find1(a),find1(b));
    return val[root];
}
int main()
{
    while(cin>>n)
    {
        dis[0]=-1;
        rep(i,1,n)
        scanf("%d",&val[i]),f[i]=i,lson[i]=rson[i]=dis[i]=0;
        cin>>m;
        while(m--)
        cin>>a>>b,printf("%d
",work(a,b));
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/bxd123/p/11345356.html