首先吐槽题目,害的我交了三次错程序上去,题目里面说的清清楚楚,数是integer,integer,呵呵,我一开始最大最小值定义为32768,-32768,最后交了前三次的结果都是Wrong Answer,后来我觉得实在没有什么地方可以改了,就把最大最小值改成long下的值,直接AC,程序效率相当之低,几乎是踩着线过数据的。
题目意思很清楚,背景故事什么的没细看,总之意思就是给你N个数,以及一个K,现在让你求[0,K-1],[1,K],...,[N-k,N-1]这些区间中的最大最小值。
对于区间问题,我首选的还是线段树,正好上次acm校赛线段树的失利历历在目,所以再写一次线段树很有必要。
代码:
#include <cstdio> #include <cstring> #include <cstdlib> #define MAXN 1000000 #define MAX 2147483647 #define MIN -2147483647 struct linet { int l , r; int max , min; }; int N , K , NN = 0; int a[MAXN]; linet tree[MAXN*3]; inline int miner(int x , int y) { if (x < y) return x; return y; } inline int maxer(int x , int y) { if (x > y) return x; return y; } void create(int l , int r , int n) { NN = maxer(NN,n); tree[n].l = l; tree[n].r = r; if (l == r) { tree[n].max = tree[n].min = a[l]; } else { int mid = (l+r) >> 1; create(l,mid,n*2+1); create(mid+1,r,n*2+2); tree[n].max = maxer(tree[n*2+1].max,tree[n*2+2].max); tree[n].min = miner(tree[n*2+1].min,tree[n*2+2].min); } } int getmin(int l , int r , int n) { if (l <= tree[n].l && tree[n].r <= r) return tree[n].min; if (tree[n].r < l || tree[n].l > r) return MAX; int p1 = MAX, p2 = MAX; if (n*2+1 <= NN) p1 = getmin(l,r,n*2+1); if (n*2+2 <= NN) p2 = getmin(l,r,n*2+2); return miner(p1,p2); } int getmax(int l , int r , int n) { if (l <= tree[n].l && tree[n].r <= r) return tree[n].max; if (tree[n].r < l || tree[n].l > r) return MIN; int p1 = MIN, p2 = MIN; if (n*2+1 <= NN) p1 = getmax(l,r,n*2+1); if (n*2+2 <= NN) p2 = getmax(l,r,n*2+2); return maxer(p1,p2); } int main () { scanf("%d%d",&N,&K); for (int i = 0;i < N;i++) scanf("%d",&a[i]); create(0,N-1,0); printf("%d",getmin(0,K-1,0)); for (int i = 1;i <= N-K;i++) printf(" %d",getmin(i,i+K-1,0)); printf("\n%d",getmax(0,K-1,0)); for (int i = 1;i <= N-K;i++) printf(" %d",getmax(i,i+K-1,0)); printf("\n"); return 0; }
尽管早有心理准备,知道线段树效率应该很低,还特地换成类C语句来写,想稍微提高点速度,但是效果依然不行。
测试结果: