一开始有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; }