http://acm.hdu.edu.cn/showproblem.php?pid=3564

(1)和今天刚做过的一道题十分相似(夜间插队问题hdu2828),从后面起算,因为最后面的数的位置是固定的,而其他数的位置被其后面的树影响着。

(2)一个易错点,在insert()函数中:

if(p<=sum[rt<<1]) insert(p, val, lson);
else insert(p-sum[rt<<1], val, rson);

  注意每个字段的含义(sum[]数组是空位的个数,p是需要预留的空位数),很多时候不加思考,就写错成了:  

if(p<=m) insert(p, val, lson);
else insert(p, val, rson);

      这是完全没有注意变量的具体含义,机械式地敲代码的结果(为此,我WA了两次。。)

(3)二分查找,快速找到相应的位置。

(4)关于pos[i]数组的具体含义。该数组是在insert()函数下算得的,i 既是数的编号,即第几个插入,又是对应的数的值,pos[i]是所有点都插入后各个

       数字对应的下标(最终位置)。

(5)注意到后面插入的数的值总是比前面插入的数大,所以二分查找的查找根据是它的最终位置,而不是自己本身的值(这点很难把握),即:

ans[start]=pos[i];

       而不是:

ans[start]=i;

       更多细节参见代码。

具体代码:

View Code
#include<stdio.h>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
const int maxn=101000;
int t, n;
int data[maxn], pos[maxn];
int sum[maxn<<2];
int tot, ans[maxn];
void build(int l, int r, int rt)
{
    sum[rt]=r-l+1;
    if(l==r)
        return ;
    int m=l+r>>1;
    build(lson);
    build(rson);
}
void insert(int p, int val, int l, int r, int rt)
{
    if(l==r)
    {
        sum[rt]=0;
        pos[val]=l;
        return ;
    }
    int m=l+r>>1;
    if(p<=sum[rt<<1]) insert(p, val, lson);
    else insert(p-sum[rt<<1], val, rson);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
int main()
{
    while(scanf("%d", &t)!=EOF)
    {
        int cas=0;
        while(t--)
        {
            printf("Case #%d:\n", ++cas);
            scanf("%d", &n);
            build(0, n, 1);
            for(int i=0;i<n;i++)
                scanf("%d", &data[i]);
            for(int i=n-1;i>=0;i--)
            {
                insert(data[i]+1, i+1, 0, n, 1);
            }
            tot=0;
            for(int i=1;i<=n;i++)
            {
                if(tot==0||pos[i]>ans[tot])
                {
                    ans[++tot]=pos[i];
                }
                else
                {
                    int start=1, tail=tot, mid;
                    while(start<=tail)
                    {
                        mid=start+tail>>1;
                        if(pos[i]<=ans[mid]) tail=mid-1;
                        else start=mid+1;
                    }
                    ans[start]=pos[i];
                }
                printf("%d\n", tot);
            }
            printf("\n");
        }
    }
    return 0;
}