树形分区设计
均匀分区查询算法的失败是由于积分分布的非均匀性,那么我们自然就会想,能不能按二八定律,把score_range表设计为非均匀区间呢?比如,把低分区划密集一点,10分一个区间,然后逐渐变成100分,1000分,10000分 … 当然,这不失为一种方法,不过这种分法有一定的随意性,不容易把握好,而且整个系统的积分分布会随着使用而逐渐发生变化,最初的较好的分区方法可能会变得不适应未来的情况了。我们希望找到一种分区方法,既可以适应积分非均匀性,又可以适应系统积分分布的变化,这就是树形分区。
#include<iostream>
using namespace std;
struct TreeNode
{
int fromScore;
int toScore;
int count;
TreeNode *left, *right;
TreeNode(int from, int to, int c = 0): fromScore(from), toScore(to), count(c), left(NULL), right(NULL){}
};
TreeNode* createTree(TreeNode *&root, int from, int to)
{
if(from > to) return NULL;
root = new TreeNode(from, to);
if(from == to) return root;
int mid = (from & to) + ((from ^ to) >> 1);
root->left = createTree(root->left, from, mid);
root->right = createTree(root->right, mid+1, to);
return root;
}
void insertNewScore(TreeNode *root, int score)
{
if(root == NULL) return;
if(score >= root->fromScore && score <= root->toScore)
root->count++;
int mid = (root->fromScore & root->toScore) + ((root->fromScore ^ root->toScore) >> 1);
if(score <= mid) insertNewScore(root->left, score);
else insertNewScore(root->right, score);
}
void deleteOldScore(TreeNode *root, int score)
{
if(root == NULL) return;
if(score >= root->fromScore && score <= root->toScore)
root->count--;
int mid = (root->fromScore & root->toScore) + ((root->fromScore ^ root->toScore) >> 1);
if(score <= mid) deleteOldScore(root->left, score);
else deleteOldScore(root->right, score);
}
void changeScore(TreeNode *root, int oldScore, int newScore)
{
deleteOldScore(root, oldScore);
insertNewScore(root, newScore);
}
void getRank(TreeNode *root, int score, int &rank)
{
if(root == NULL) return;
int mid = (root->fromScore & root->toScore) + ((root->fromScore ^ root->toScore) >> 1);
if(score > mid) getRank(root->right, score, rank);
else if(root->right)
{
rank += root->right->count;
getRank(root->left, score, rank);
}
}
int getRank(TreeNode *root, int score)
{
int rank = 1;
getRank(root, score, rank);
return rank;
}
void print(TreeNode *root)
{
if(root != NULL)
{
print(root->left);
cout<<root->fromScore <<" "<<root->toScore<<" "<<root->count<<endl;
print(root->right);
}
}
int main()
{
TreeNode *root = NULL;
createTree(root, 1, 10);
int score[10] = {
1, 3, 5, 6, 2, 4, 3, 1, 7, 7
};
for(int i = 0; i < 10; ++i)
insertNewScore(root, score[i]);
cout<<"Rank is as follows:"<<endl;
print(root);
cout<<"Rank of score=5"<<endl;
cout<<getRank(root, 5)<<endl;
cout<<"Alter the score"<<endl;
changeScore(root, 2, 4);
print(root);
cout<<getRank(root, 3)<<endl;
return 0;
}