1. 程式人生 > >洛谷P1886 滑動窗口(POJ.2823 Sliding Window)(區間最值)

洛谷P1886 滑動窗口(POJ.2823 Sliding Window)(區間最值)

最大 ide dma include names target org void blog

To 洛谷.1886 滑動窗口 To POJ.2823 Sliding Window

題目描述

現在有一堆數字共N個數字(N<=10^6),以及一個大小為k的窗口。現在這個從左邊開始向右滑動,每次滑動一個單位,求出每次滑動後窗口中的最大值和最小值。

例如:

The array is [1 3 -1 -3 5 3 6 7], and k = 3.

技術分享

輸入輸出格式

輸入格式:

輸入一共有兩行,第一行為n,k。

第二行為n個數(<INT_MAX).

輸出格式:

輸出共兩行,第一行為每次窗口滑動的最小值

第二行為每次窗口滑動的最大值

輸入輸出樣例

輸入樣例#1:
8 3
1 3 -1 -3 5 3 6 7
輸出樣例#1:
-1 -3 -3 -3 3 3
3 3 5 5 6 7

說明

50%的數據,n<=10^5

100%的數據,n<=10^6

代碼:

洛谷70分TLE的線段樹

技術分享
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int N=1000005;
 5 
 6 int n,k,From,To,Min[N<<2],Max[N<<2];
7 8 void read(int &now) 9 { 10 now=0;int f=1;char c=getchar(); 11 while(c<0||c>9) 12 { 13 if(c==-)f=-1; 14 c=getchar(); 15 } 16 while(c>=0&&c<=9)now=now*10+c-0,c=getchar(); 17 now*=f; 18 } 19 20 inline void PushUp(int
rt) 21 { 22 Min[rt]=min(Min[rt<<1],Min[rt<<1|1]); 23 Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); 24 } 25 26 void Build(int l,int r,int rt) 27 { 28 if(l==r) 29 { 30 int t; 31 read(t); 32 Min[rt]=Max[rt]=t; 33 return; 34 } 35 int m=(l+r)>>1; 36 Build(l,m,rt<<1); 37 Build(m+1,r,rt<<1|1); 38 PushUp(rt); 39 } 40 41 int QueryMax(int l,int r,int rt,int L,int R) 42 { 43 if(L<=l && r<=R) return Max[rt]; 44 int m=(l+r)>>1,res=(1<<31); 45 if(L<=m) res=max(res,QueryMax(l,m,rt<<1,L,R)); 46 if(m<R) res=max(res,QueryMax(m+1,r,rt<<1|1,L,R)); 47 return res; 48 } 49 50 int QueryMin(int l,int r,int rt,int L,int R) 51 { 52 if(L<=l && r<=R) return Min[rt]; 53 int m=(l+r)>>1,res=(1<<30); 54 if(L<=m) res=min(res,QueryMin(l,m,rt<<1,L,R)); 55 if(m<R) res=min(res,QueryMin(m+1,r,rt<<1|1,L,R)); 56 return res; 57 } 58 59 int main() 60 { 61 read(n);read(k); 62 Build(1,n,1); 63 //From=1;To=k; 64 for(register int i=1;i<=n-k+1;i++)//,From++,To++ 65 printf("%d ",QueryMin(1,n,1,i,i+k-1)); 66 printf("\n"); 67 //From=1;To=k; 68 for(register int i=1;i<=n-k+1;i++)//,From++,To++ 69 printf("%d ",QueryMax(1,n,1,i,i+k-1)); 70 return 0; 71 }
TLE

常數優化十分可觀的zkw線段樹(然而我不會用)

技術分享
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int N=1000005;
 5 
 6 int n,k,M,Tree[N<<2];
 7 
 8 void read(int &now)
 9 {
10     now=0;int f=1;char c=getchar();
11     while(c>9||c<0)
12     {
13         if(c==-)f=-1;
14         c=getchar();
15     }
16     while(c>=0&&c<=9)now=(now<<3)+(now<<1)+c-0,c=getchar();
17     now*=f;
18 }
19 
20 void BuildMin(int n)
21 {
22     for(int i=M-1;i;--i)
23       Tree[i]=min(Tree[i<<1],Tree[i<<1|1]);
24 }
25 
26 void BuildMax(int n)
27 {
28     for(int i=M-1;i;--i)
29       Tree[i]=max(Tree[i<<1],Tree[i<<1|1]);
30 }
31 
32 int QueryMin(int s,int t,int res)
33 {
34     for(s+=M,t+=M;s^t^1;s>>=1,t>>=1)
35     {
36         if(~s&1) res=min(res,Tree[s^1]);
37         if(t&1) res=min(res,Tree[t^1]);
38     }
39     return res;
40 }
41 
42 int QueryMax(int s,int t,int res)
43 {
44     for(s+=M,t+=M;s^t^1;s>>=1,t>>=1)
45     {
46         if(~s&1) res=max(res,Tree[s^1]);
47         if(t&1) res=max(res,Tree[t^1]);
48     }
49     return res;
50 }
51 
52 int main()
53 {
54     read(n);read(k);
55     for(M=1;M<=n+1;M<<=1);
56     for(int i=M+1;i<=M+n;i++)
57       read(Tree[i]);
58     BuildMin(n);
59     for(int i=0;i<=n-k;++i)
60       printf("%d ",QueryMin(i,i+k+1,1e9));
61     printf("\n");
62     BuildMax(n);
63     for(int i=0;i<=n-k;++i)
64       printf("%d ",QueryMax(i,i+k+1,-1e9));
65     return 0;
66 }
AC

洛谷P1886 滑動窗口(POJ.2823 Sliding Window)(區間最值)