poj中的一些线段树

poj2828

链接:http://poj.org/problem?id=2828

题解:

初始状态

首先是插入3 69

14结点有4个位置,

12结点有2个位置,小于3,因此放到14结点右孩子,且14结点空位置减1

到了14右孩子后,只要找到第3-2=1个位置即可,而34结点的左孩子33含有1个空位置,1>=1,所以放到33位置了。

 

插入2 33

 

★关键是这里如何处理★

插入2 51

此时14的左孩子只有1个位置,1<2,所以只能放到14的右孩子34

34的左孩子有0个位置,所以只能放在34的右孩子44上。

 

插入1 77

#include<iostream>
#include<cstdio>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn=200001;
int sum[maxn<<2];
int pos[maxn],val[maxn],seq[maxn];
int id;
void build(int l,int r,int rt)    //建树过程,跟节点为其整个区间的长度
{
    sum[rt]=r-l+1;
    if(l==r)
        return;
    int m=(l+r)/2;
    build(lson);
    build(rson);
}
void update(int p,int l,int r,int rt)  //更新过程
{
    sum[rt]--;
    if(l==r)
    {
        id=l;
        return;
    }
    int m=(l+r)/2;
    if(sum[rt<<1]>=p)
    update(p,lson);
    else
    {
        p-=sum[rt<<1];
        update(p,rson);
    }
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        build(1,n,1);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&pos[i],&val[i]);
        for(int i=n;i>=1;i--)     //从最后一步操作开始往上进行
        {
            update(pos[i]+1,1,n,1);
            seq[id]=val[i];
        }
        printf("%d",seq[1]);
        for(int i=2;i<=n;i++)
            printf(" %d",seq[i]);
            printf("
");
    }
    return 0;
}


原文地址:https://www.cnblogs.com/wolf940509/p/6617123.html