扩张的红黑树,每个结点增加一个size属性。
解题思路:
按输入顺序,不断insert,在insert时,判断
当往下走(寻找要插入的位置)时,走到一个结点(设为A)的左子树时,z小于A和A右子树,且z出现在A和A右子树之后(对于输入数组来说),故z和A、z和A右子树的所有结点形成逆序对。
#include<cstdio>
#include<queue>
#include<iostream>
#include<algorithm>
//#include<windows.h>
using namespace std;
enum RBCOLOR{RED,BLACK};
class RBNODE{
public:
int key;
RBNODE* left;
RBNODE* right;
RBNODE* parent;
RBCOLOR color;
int size;
RBNODE(int key){this->key=key;}
};
class RB{
public:
RBNODE *root;
RBNODE *nil;
int inversion_count;
RB(){nil=new RBNODE('#');root=nil;nil->color=BLACK;inversion_count=0;nil->size=0;}
~RB(){delete_tree(root);}
void LEFT_ROTATE(RBNODE* x)
{
RBNODE* y=x->right;x->right=y->left;
if(y->left!=nil) y->left->parent=x;
y->left=x;
if(x->parent==nil) root=y;
else if(x==x->parent->left) x->parent->left=y;
else x->parent->right=y;
y->parent=x->parent;x->parent=y;
y->size=x->size;
x->size=x->left->size+x->right->size+1;
}
void RIGHT_ROTATE(RBNODE* y)
{
RBNODE* x=y->left;y->left=x->right;
if(x->right!=nil) x->right->parent=y;
x->right=y;
if(y->parent==nil) root=x;
else if(y->parent->left==y) y->parent->left=x;
else y->parent->right=x;
x->parent=y->parent;y->parent=x;
x->size=y->size;
y->size=y->left->size+y->right->size+1;
}
void RB_INSERT(RBNODE* z)
{
RBNODE* parent=nil;
RBNODE* node=root;
while(node!=nil){
parent=node;parent->size++;
if(z->key<node->key){
inversion_count+=node->right->size+1;
node=node->left;
}
else node=node->right;
}
//cout<<inversion_count<<endl;
if(parent==nil) root=z;
else if(z->key<parent->key) parent->left=z;
else parent->right=z;
z->parent=parent;z->color=RED;
z->left=z->right=nil;z->size=1;
RB_INSERT_FIXUP(z);
// cout<<"node:"<<z->key<<endl;
// preorder_traverse();
// inorder_traverse();
// postorder_traverse();
}
void RB_INSERT_FIXUP(RBNODE* z)
{
while(z->parent->color==RED){
if(z->parent==z->parent->parent->left){
RBNODE* uncle=z->parent->parent->right;
if(uncle->color==RED){
z->parent->color=BLACK;//case 1
uncle->color=BLACK;//case 1
z->parent->parent->color=RED;//case 1
z=z->parent->parent;//case 1
}
else{
if(z==z->parent->right){
z=z->parent;LEFT_ROTATE(z);//case 2
}
z->parent->color=BLACK;//case 3
z->parent->parent->color=RED;//case 3
RIGHT_ROTATE(z->parent->parent);//case 3
}
}else{//same as "then" clause with right and left exchanged
RBNODE* uncle=z->parent->parent->left;
if(uncle->color==RED){
z->parent->color=BLACK;//case 1
uncle->color=BLACK;//case 1
z->parent->parent->color=RED;//case 1
z=z->parent->parent;//case 1
}
else{
if(z==z->parent->left){
z=z->parent;RIGHT_ROTATE(z);//case 2
}
z->parent->color=BLACK;//case 3
z->parent->parent->color=RED;//case 3
LEFT_ROTATE(z->parent->parent);//case 3
}
}
}
root->color=BLACK;
}
void delete_tree(RBNODE* node)
{
if(node!=nil){
delete_tree(node->left);
delete_tree(node->right);
delete node;
}
}
// void level_traverse()
// {
// queue<RBNODE*> Q;
// if(root!=nil) Q.push(root);
// cout<<Q.front()->key<<endl;
// int height=TREE_HEIGHT(root)-1;
// for(int i=0;i<=height;i++){//按层打印
// print_space(1<<(height-i));//在一层的最前打印2^(height-i)个空格
// int node_number=1<<i;//该层结点数
// for(int j=0;j<node_number;j++){//打印第i层结点
// RBNODE* node=Q.front();
// if(node==nil){Q.push(nil);Q.push(nil);}
// else{Q.push(node->left);Q.push(node->right);}
// print_node(node);Q.pop();
// print_space((1<<(height-i+1))-1);
// }
// putchar('\n');
// }
// }
// void print_node(RBNODE* node)
// {
// if(node!=nil){
// if(node->color==RED) color(12,0);
// putchar(node->key);
// color(8,0);
// }
// else putchar(' ');
// }
// void print_space(int num)
// {
// CONSOLE_SCREEN_BUFFER_INFO bInfo;
// GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&bInfo);
// COORD c=bInfo.dwCursorPosition;
// while(num--) putchar(' ');
// }
// int TREE_HEIGHT(RBNODE* node)
// {
// if(node==nil) return 0;
// else return max(TREE_HEIGHT(node->left),TREE_HEIGHT(node->right))+1;
// }
// void color(unsigned short int fore,unsigned short int back)
// {
// HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
// SetConsoleTextAttribute(hOut,fore+back*16);
// }
};
int main()
{
//freopen("1.txt","r",stdin);
int n;
scanf("%d",&n);
for(int j=1;j<=n;j++){
RB* TREE=new RB();
int key,m;scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%d",&key);
TREE->RB_INSERT(new RBNODE(key));
}
//TREE->level_traverse();
printf("Scenario #%d:\n%d\n",j,TREE->inversion_count);
//cout<<"Scenario #"<<j<<":"<<endl<<TREE->inversion_count<<endl;
if(j!=n) putchar('\n');
delete TREE;//删除这句也可过,耗时少很多,不过耗比较多空间。时空权衡呗。反正都能过。
}
return 0;
}