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