#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=32010;
//類似一棵二叉樹,加上數據和維護的區間信息
struct Node
{
int l,r;
int data;
};
//利用數組來存儲二叉樹
Node tree[maxn*4];
int ans[maxn];
int n;
//注意這裏的pos是在樹上的位置(tree的索引),而相應的l和r值得是info裏面的下標
//pos == 1
// 1
// 2 3
// 4 5 6 7
// ... ...
void buildTree(int pos,int l,int r)
{
tree[pos].l=l;
tree[pos].r=r;
//初始化數據爲0
tree[pos].data=0;
//達到底部返回
if(l==r)
return;
//類似歸併排序,繼續遞歸
int mid=(l+r)>>1;
//建立左子樹
buildTree(pos<<1,l,mid);
//建立右子樹
buildTree((pos<<1)+1,mid+1,r);
}
//注意這裏的id是info下標,pos是對應樹上的位置,順着pos向下滑動
void update(int id,int pos,int dx)
{
//找到則更新數據
if(tree[pos].l==tree[pos].r)
{
tree[pos].data+=dx;
return;
}
//沒找到則繼續在左子樹或者右子樹中找
//說過l,r也是info上的信息,所以要把id和mid相比較
int mid=(tree[pos].l+tree[pos].r)>>1;
if(id<=mid)
update(id,pos<<1,dx);
else
update(id,(pos<<1)+1,dx);
//向上更新一次
tree[pos].data=tree[pos<<1].data+tree[(pos<<1)+1].data;
}
int query(int l,int r,int pos)
{
//找到區間返回
if(tree[pos].l==l && tree[pos].r==r)
return tree[pos].data;
int mid=(tree[pos].l+tree[pos].r)>>1;
//看看具體在那個巨劍
if(r<mid)
return query(l,r,pos*2);
else if(l>mid)
return query(l,r,pos*2+1);
else
return query(l,mid,pos*2)+query(mid+1,r,pos*2+1);
}
int main()
{
cin>>n;
int x,y;
memset(ans,0,sizeof(ans));
memset(tree,0,sizeof(tree));
buildTree(1,1,maxn);
while(n--)
{
cin>>x>>y;
ans[query(1,n,x)]++;
update(x,1,1);
}
for(int i=1;i<=n;i++)
cout<<ans[i]<<endl;
return 0;
}
Node:線段樹的單點更新
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.