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

(1)用到了线段树求最大值。线段树求最值、求和是两种重要工具,很多题目要以此为基石(很多时候第一眼看不出来要用上他们)。

   本题的本质为求一段区间的最大值,每读入一个新的数据,都要递归地与该最大值判定,最底层时更新信息,得到结果。

(2)线段树输入数据较多,不宜使用C++输入输出数据流(会超时的)。

(3)多开了一个数组,没有赋初值,直接运算,但并没有对结果产生影响(独立的变量,不影响其他数的值),结果判定为WA。。。

(4)注意到一个优化:h=min(h, n);否则要开一个1亿的数组,显然是不现实的。

具体代码:

View Code
#include<stdio.h>
#include<algorithm>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
const int maxn=201000;
int data[maxn], sum[maxn<<2];
int h, w, n;
int ans;
void build(int l, int r, int rt)
{
    sum[rt]=w;
    if(l==r)  return ;
    int m=l+r>>1;
    build(lson);
    build(rson);
}
void update(int val, int l, int r, int rt)
{
    if(l==r)
    {
        ans=l;
        sum[rt]-=val;
        return ;
    }
    int m=l+r>>1;
    if(val<=sum[rt<<1]) update(val, lson);
    else update(val, rson);
    sum[rt]=max(sum[rt<<1], sum[rt<<1|1]);
}
int main()
{
    int i, j, k;
    while(scanf("%d%d%d", &h, &w, &n)!=EOF)
    {
        int len=min(h, n);
        build(1, len, 1);
        for(i=1;i<=n;i++)
        {
            int a;
            scanf("%d", &a);
            ans=-1;
            if(a<=sum[1])
            {
                update(a, 1, len, 1);
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}


上面的代码是在函数中计算出结果,下面的代码是利用函数返回结果(本质没变,细节稍变):

View Code
#include<stdio.h>
#include<algorithm>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
const int maxn=201000;
int sum[maxn<<2];
int h, w, n;
int ans;
void build(int l, int r, int rt)
{
    sum[rt]=w;
    if(l==r)  return ;
    int m=l+r>>1;
    build(lson);
    build(rson);
}
int update(int val, int l, int r, int rt)
{
    if(l==r)
    {
        sum[rt]-=val;
        return l;
    }
    int m=l+r>>1, ret;
    if(val<=sum[rt<<1]) ret=update(val, lson);
    else ret=update(val, rson);
    sum[rt]=max(sum[rt<<1], sum[rt<<1|1]);
    return ret;
}
int main()
{
    int i, j ,k;
    while(scanf("%d%d%d", &h, &w, &n)!=EOF)
    {
        int len=min(h, 200000);
        build(1, len, 1);
        for(i=1;i<=n;i++)
        {
            int a;
            scanf("%d", &a);
            if(a<=sum[1])
            {
                printf("%d\n", update(a, 1, len, 1));
            }
            else 
                printf("-1\n");
        }
    }
    return 0;
}

超时代吗(C++输入输出流):

View Code
#include<iostream>
#include<stdio.h>
#include<algorithm>
#define MAXSIZE 200000
using namespace std;
int a[MAXSIZE<<2];
int h,w,n;

void build(int l,int r,int rt)
{
    a[rt]=w;
    if(l==r) return;
    int m((l+r)>>1);
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
}
int query(int x,int l,int r,int rt)
{
    if(l==r)
    {
        a[rt]-=x;
        return l;
    }
    int m((l+r)>>1);
    int tp=(a[rt<<1]>=x)?query(x,l,m,rt<<1):query(x,m+1,r,rt<<1|1) ;
    a[rt]=max(a[rt<<1],a[rt<<1|1]);
    return tp;
}
int main()
{
    int i,x;
    while(scanf("%d%d%d", &h, &w, &n)!=EOF)
    {
        int len=min(h, 200000);
        build(1,len,1);
        for(i=1;i<=n;i++)
        {
            cin>>x;
            if(x>a[1])
                cout<<-1<<endl;
            else
                cout<<query(x,1,len,1)<<endl;
        }
    }
    return 0;
}

WA(多余的data数组,未赋初值的运算,神奇般地WA):

View Code
#include<stdio.h>
#include<algorithm>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
const int maxn=201000;
int data[maxn], sum[maxn<<2];
int h, w, n;
int ans;
void build(int l, int r, int rt)
{
    sum[rt]=w;
    if(l==r)  return ;
    int m=l+r>>1;
    build(lson);
    build(rson);
}
void update(int val, int l, int r, int rt)
{
    if(l==r)
    {
        ans=l;
        sum[rt]-=val;
        data[rt]-=val;
        return ;
    }
    int m=l+r>>1;
    if(val<=sum[rt<<1]) update(val, lson);
    else update(val, rson);
    sum[rt]=max(sum[rt<<1], sum[rt<<1|1]);
}
int main()
{
    int i, j ,k;
    while(scanf("%d%d%d", &h, &w, &n)!=EOF)
    {
        int len=min(h, 200000);
        build(1, len, 1);
        for(i=1;i<=n;i++)
        {
            int a;
            scanf("%d", &a);
            ans=-1;
            if(a<=sum[1])
            {
                update(a, 1, len, 1);
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}