败方树

2:败方树

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

给定一个整数数组,要求对数组中的元素构建败方树(数组相邻元素两两比较,从第一个元素开始)。之后修改数组中的元素,要求输出初始构建以及修改后得到的败方树的所有内部结点代表的整数(从左到右从上到下输出)


输入
第一行为数组的元素个数n和修改的次数m。
第二行为n个整数,即数组的元素。
接下来m行代表m次修改操作,每次操作修改数组中的一个元素,每一行包括两个整数,第一个为被修改元素在数组中的标号,第二个为修改之后的元素值。
输出
输出m+1行。
第一行为初始构建的败方树的所有内部结点代表的整数(按照树的结点从左到右从上到下的顺序输出)
接下来m行为接下来m次修改后得到的败方树的所有内部结点代表的整数(按照树的结点从左到右从上到下的顺序输出)
样例输入
8 110 9 20 6 16 12 90 173 15
样例输出
6 12 9 17 10 20 16 909 12 15 17 10 20 16 90

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
using namespace std;
int a[1005];
int B[2005];
int n,m,Index,val,offset,lowext;
int Winner(int x,int y)
{
	if(a[x]>a[y])return y;
	else return x;
}
int Loser(int x,int y)
{
	if(a[x]>a[y])return x;
	else return y;
}
void Play(int father,int l,int r)
{
	int tmp1=0,tmp2=0;
	B[father]=Loser(l,r);
	tmp1=Winner(l,r);
	while(father>1&&father%2==1)
	{
		tmp2=Winner(tmp1,B[father/2]);
		B[father/2]=Loser(tmp1,B[father/2]);
		tmp1=tmp2;
		father/=2;
	}
	B[father/2]=tmp1;
}
void replay(int i)
{
	int father;
	if(i<=lowext)
		father=(i+offset)/2;
	else
		father=(i-lowext+n-1)/2;
	B[0]=Winner(i,B[father]);
	B[father]=Loser(i,B[father]);
	while(father/2>=1)
	{
		int tmp=Winner(B[father/2],B[0]);
		B[father/2]=Loser(B[father/2],B[0]);
		B[0]=tmp;
		father/=2;
	}
}
void Build()
{
	int s,i;
	for(s=1;s*2<=n-1;s<<=1);
	lowext=2*(n-s);
	offset=2*s-1;
	for(i=2;i<=lowext;i+=2)
	{
		Play((offset+i)/2,i-1,i);
	}
	if(n%2==1)
	{
		Play(n/2,B[(n-1)/2],lowext+1);
		i=lowext+3;
	}
	else
	{
		i=lowext+2;
	}
	for(;i<=n;i+=2)
	{
		Play((i-lowext+n-1)/2,i-1,i);
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;++i)
		cin>>a[i];
	Build();
	for(int i=0;i<n;++i)
	{
		cout<<a[B[i]]<<" ";
	}
	cout<<endl;
	while(m--)
	{
		cin>>Index>>val;
		a[Index+1]=val;
		replay(Index+1);
		for(int i=0;i<n;++i)
		{
			cout<<a[B[i]]<<" ";
		}
		cout<<endl;
	}
	return 0;
}



版权声明:本文为m0_37975647原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。