poj2828,很好的线段树思路

来源:互联网 发布:日本人素质高 知乎 编辑:程序博客网 时间:2024/05/16 01:47

题意就不解释了,大家尽量不要搜索题意,还是要自己看题分析题意算法。

这个题我看到后第一个就是用vector直接insert,然后果断超时....

然后看了一下别人的思路发现这个线段树用的很好啊。

思路:逆序遍历,线段树结点存储的是当前区域的空位置数量。

最后一次插入的点就在插入的位置pos。

然后往前遍历,倒数第二次插入就是要找到第pos+1个空位置,以此类推。

以下图片转自http://www.cnblogs.com/CheeseZH/archive/2012/04/29/2476134.html:


插入3,69.那么1,4区间内包含4个空位置,然后--;左子树只有两个空位置不够3个,则进入右子树,而且右子树的空位置包括左子树的空位置。

所以用3-2=1,这时再进入左子树放入即可。详细见代码update。

后面大致相同了


相信你已经看清了。ok,仔细想一下,然后再看代码。(顺带问一句怎么把代码贴的漂亮点?就像大多数博客那样。)


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
#include<map>
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
const int ma=200000+10;
const int inf=1000000007;
int sum[ma<<2],p[ma],v[ma],a[ma],id;
int n;
void build(int l,int r,int rt)
{
    sum[rt]=r-l+1;
    int m=(l+r)>>1;
    if(l==r)return;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int t,int l,int r,int rt)
{
    sum[rt]--;
    if(l==r){
        id=l;
        return;
    }
    int m=(l+r)>>1;
    if(sum[rt<<1]>=t)
        update(t,lson);
    else{
        t-=sum[rt<<1];
        update(t,rson);
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        build(1,n,1);
        for(int i=0;i<n;i++)
            scanf("%d%d",&p[i],&v[i]);
        for(int i=n-1;i>=0;i--)
        {
            update(p[i]+1,1,n,1);
            a[id]=v[i];
        }
        printf("%d",a[1]);
        for(int i=2;i<=n;i++)
            printf(" %d",a[i]);
        printf("\n");
    }
    return 0;
}

0 0
原创粉丝点击