题目:
520161010452 33 43 54 51 5 Sample Output855-110分析:
每一只猴子看做一个结点,建立左偏树,树根维护最大值。若两结点树根相同,说明两只猴子是朋友,输出-1;
否则,两根节点值减半,删除,重新与原树合并得两新树,两新树合并后返回根节点值。
本题仅涉及到左偏树部分操作。
左偏树入门:
http://wenku.baidu.com/view/1c18eff9aef8941ea76e051b.html
http://wenku.baidu.com/view/004aa1ee19e8b8f67c1cb9d4.html?from=search
http://sunmoon-template.blogspot.ca/2014_12_01_archive.html
代码:
#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<ctype.h> //tower()#include<set>#include<iomanip>// cout<<setprecision(1)<<fixed<<a;#include<vector> #include<time.h> #include<assert.h> //assert#include<cmath> #include<algorithm>#include<bitset>#include<limits.h>#include<stack>#include<queue>using namespace std;const int maxn=100050;const int inf=INT_MAX-100;struct node{ int val,dis,lt,rt,fa;//fa 父节点}ltree[maxn];int n,q,t;void maketree(int a,int k){//结点成树 a结点值为k ltree[a].val=k; ltree[a].fa=a; ltree[a].lt=ltree[a].rt=0; ltree[a].dis=(a==0)?-1:0;}int find(int x){//非递归路径压缩,返回所在树根节点 int s,k,j; s=k=x; while(s!=ltree[s].fa) s=ltree[s].fa; while(k!=s){ j=ltree[k].fa; ltree[k].fa=s; k=j; } return s;}int merge(int a,int b){//两棵树合并 改变rt,dis,fa if(a==0) return b; if(b==0) return a; if(ltree[a].val<ltree[b].val) swap(a,b); ltree[a].rt=merge(ltree[a].rt,b);//b接在a最右边 int &l=ltree[a].lt,&r=ltree[a].rt;//左右子树的引用,取别名,不另占内存,值同时修改 ltree[r].fa=a;//ltree[l].fa= if(ltree[l].dis<ltree[r].dis) swap(l,r);//维持左偏性 if(r==0) ltree[a].dis=0; else ltree[a].dis=ltree[r].dis+1; return a;}int solve(int a,int b){ int tmp,ta,tb; a=find(a); b=find(b); if(a==b) return -1;// ltree[ltree[a].lt].fa=ltree[a].lt;// ltree[ltree[a].rt].fa=ltree[a].rt; ltree[a].val>>=1; tmp=merge(ltree[a].lt,ltree[a].rt); ltree[a].dis=ltree[a].lt=ltree[a].rt=0; ta=merge(tmp,a);// ltree[ltree[b].lt].fa=ltree[b].lt;// ltree[ltree[b].rt].fa=ltree[b].rt; ltree[b].val>>=1; tmp=merge(ltree[b].lt,ltree[b].rt); ltree[b].dis=ltree[b].lt=ltree[b].rt=0; tb=merge(tmp,b); tmp=merge(ta,tb); ltree[tmp].fa=ltree[ta].fa=ltree[tb].fa=tmp; return ltree[tmp].val;}int main(){//795MS 3540K while(~scanf("%d",&n)){ for(int i=1;i<=n;++i){ scanf("%d",&t); maketree(i,t); }// maketree(0,0); scanf("%d",&q); int c,d; for(int i=0;i<q;++i){ scanf("%d%d",&c,&d); printf("%d/n",solve(c,d)); } } return 0; }
新闻热点
疑难解答