给定一个整数数组,要求对数组中的元素构建败方树(数组相邻元素两两比较,从第一个元素开始)。之后修改数组中的元素,要求输出初始构建以及修改后得到的败方树的所有内部结点代表的整数(从左到右从上到下输出)
输入
第一行为数组的元素个数n和修改的次数m。
第二行为n个整数,即数组的元素。
接下来m行代表m次修改操作,每次操作修改数组中的一个元素,每一行包括两个整数,第一个为被修改元素在数组中的标号,第二个为修改之后的元素值。
输出
输出m+1行。
第一行为初始构建的败方树的所有内部结点代表的整数(按照树的结点从左到右从上到下的顺序输出)
接下来m行为接下来m次修改后得到的败方树的所有内部结点代表的整数(按照树的结点从左到右从上到下的顺序输出)
样例输入
8 1
10 9 20 6 16 12 90 17
3 15
样例输出
6 12 9 17 10 20 16 90
9 12 15 17 10 20 16 90
分析过程都在代码中做出了标注,代码如下:
#include<iostream>
#include<vector>
#include<map>
using namespace std;
class loserTree
{
public:
loserTree(int* thePlayers,int n); //create the loser tree
~loserTree(){delete [] tree;delete [] temp;} //release resources
void replay(int thePlayer,int value); //replay the game
void output() const;
int* theTree(){return tree;}
private:
int* tree; //place the loser in the game,but tree[0] is final winner
int* player; //the player to compete
int* temp; //place the winner to compete
int numOfPlayer; //the number of the player to compete
int lowExt; //2*(n-s),represent the number of the bottom,s=2^(log2(n-1))
//s represent the index of the far left of the bottom
int offset; //2*s-1
int winner(int x,int y){return player[x]<=player[y]?x:y;} //return the winner
int loser(int x,int y){return player[x]>player[y]?x:y;} //return the loser
void play(int gamepoint,int leftPlayer,int rightPlayer); //to comptete,if left<=right left win,else left lose
};
loserTree::loserTree(int* thePlayers,int n)
{
tree=nullptr,temp=nullptr;
if(n<2){return;}
player=thePlayers;
numOfPlayer=n;
tree=new int[n];
temp=new int[n];
int i,s;
for(s=1;2*s<=n-1;s*=2);
lowExt=2*(n-s); //when player begins from index 1, lowExt=2*(n-s) offset=2*s-1;
offset=2*s-1;
for(i=2;i<=lowExt;i+=2)
{// players of the last layer compete
play((i+offset)/2,i-1,i);
}
//deal with the special point
if(n%2==1){ //the left player of game point is from tree[i]
play(n/2,temp[n-1],lowExt+1);
i=lowExt+3;
}else{
i=lowExt+2;
}
for(;i<=n;i+=2)
{ //players of the last but one layer compete
play((i-lowExt+n-1)/2,i-1,i);
}
tree[0]=temp[1]; //record the winner int the lose tree
}
void loserTree::play(int p,int left,int right)
{
tree[p]=loser(left,right); //when p is even,the competition only one time
temp[p]=winner(left,right); //why?p is even that means compete only occur int the last layer
//ioslate that special point with lower point
//this means the players all exists int the lose tree,continue upper until to the top
while (p % 2 == 1&& p > 1) //the index of the right player is always odd
{
tree[p/2]=loser(temp[p-1],temp[p]); // loser
temp[p/2]=winner(temp[p-1],temp[p]); // winner
p /= 2; //continue unitl reach the root
}
}
void loserTree::replay(int thePlayer,int newValue)
{
int n=numOfPlayer;
if(thePlayer<=0||thePlayer>n){
cout<<"the parameter is error"<<endl;
return;
}
player[thePlayer]=newValue;
//get the left player and the right player
int matchPoint,left,right; //game point,left player,right player
if(thePlayer<=lowExt){ //the player is on the bottom
matchPoint=(thePlayer+offset)/2;
left=2*matchPoint-offset; // unify to the left player
right=left+1;
}else{ //the player is on the last but one
matchPoint=(thePlayer-lowExt+n-1)/2;
if(2*matchPoint==n-1){ //special gamepoint
left=temp[2*matchPoint];
right=thePlayer;
}else{
left=2*matchPoint-(n-1)+lowExt;
right=left+1;
}
}
//to compete
if(thePlayer==tree[0]){//the player to replay is the previous winner!!!,ok,that's simple
for(;matchPoint>=1;matchPoint/=2)
{// and we note the left and right is not necessary,so the upper code can be simpler
int loserTemp=loser(tree[matchPoint],thePlayer);
temp[matchPoint]=winner(tree[matchPoint],thePlayer);
tree[matchPoint]=loserTemp;
thePlayer=temp[matchPoint];
}
}else{ //it's normal,but the competiton is a bit complex
tree[matchPoint]=loser(left,right); //first game
temp[matchPoint]=winner(left,right);
if(matchPoint==n-1&&n%2==1){ //second game,and it's special
matchPoint/=2;
tree[matchPoint]=loser(temp[n-1],lowExt+1); //fisrt game
temp[matchPoint]=winner(temp[n-1],lowExt+1);
}
matchPoint/=2; //then all is back to normal,continue competing
for(;matchPoint>=1;matchPoint/=2)
{
tree[matchPoint]=loser(temp[2*matchPoint],temp[2*matchPoint+1]);
temp[matchPoint]=winner(temp[2*matchPoint],temp[2*matchPoint+1]);
}
}
tree[0]=temp[1]; //place the new winner
}
void loserTree::output() const
{
for(int i=0;i<numOfPlayer;i++) //< not <=
{cout<<player[tree[i]]<<" ";}
}
int main()
{ //int players[]={0,10,9,20,6,16,12,90,17};
int n,m;
cin>>n>>m;
int* players=new int[n+1]; //the number of valid element is n
for(int i=1;i<=n;i++)
{
cin>>players[i];
}
loserTree ltree(players,n);
vector<pair<int,int>> vPair;
int index,value;
for(int i=1;i<=m;i++)
{//record the input
cin>>index>>value;
pair<int,int>ptemp(index+1,value);
vPair.push_back(ptemp);
}
ltree.output();//output the original result
cout<<endl;
for(int i=0;i<vPair.size();i++)
{//output the results
ltree.replay(vPair[i].first,vPair[i].second);
ltree.output();
cout<<endl;
}
delete [] players;
}
简化版如下
#include<iostream>
#include<vector>
#include<utility>
#include<cmath>
using namespace std;
class loserTree
{
public:
loserTree(int* thePlayer, int num) {
if (num<2) { return; }
player = thePlayer;
n = num;
tree = new int[n];
int s = log(n - 1) / log(2);
s = pow(2, s);
lowext = 2 * (n - s);
offset = 2 * s - 1;
int i = 0;
for (i = 2; i <= lowext; i += 2) {
play((i + offset) / 2, i - 1, i);
}
if (n % 2 == 1) {
play(n / 2, tree[(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);
}
}
~loserTree() { delete[] tree; }
void replay(int k, int value) {
player[k] = value;
int root = k <= lowext ? (k + offset) / 2 : (n - 1 + k - lowext) / 2;
pair<int, int> re;
for (; root >= 1; root /= 2) {
re = compete(tree[root],tree[0]);
tree[root] = re.second;
tree[0] = re.first;
}
}
void output() const {
for (int i = 0; i<n; i++){
cout << player[tree[i]] << " ";
}
}
private:
int* tree;
int* player;
int n;
int lowext;
int offset;
pair<int, int> compete(int x, int y) {
pair<int, int>re;
re.first = player[x] <= player[y] ? x : y;
re.second = player[x]>player[y] ? x : y;
return re;
}
void play(int p, int left, int right) {
pair<int, int> re = compete(left, right);
tree[p] = re.second; //loser
while (p % 2 == 1 && p>1) {
re = compete(tree[p / 2], re.first);
tree[p / 2] = re.second;
p /= 2;
}
tree[p / 2] = re.first; //winner
}
};
int main()
{
int n, m;
cin >> n >> m;
int* players = new int[n + 1];
for (int i = 1; i <= n; i++) {
cin >> players[i];
}
loserTree ltree(players, n);
ltree.output();
cout << endl;
int index, value;
for (int i = 1; i <= m; i++) {
cin >> index >> value;
ltree.replay(index+1, value);
ltree.output();
cout << endl;
}
delete[] players;
return 0;
}