Node:線段樹的單點更新

#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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章