首页 > 代码库 > 【尺取法】POJ3061 & POJ3320

【尺取法】POJ3061 & POJ3320

POJ3061-Subsequence

【题目大意】

给定长度微n的数列整数及整数s。求出总和不小于s的连续子序列的长度的最小值。如果节不存在,则输出0。

【思路】

尺取法五分钟裸裸裸~刷水刷出了罪恶感:(

基本做法:设置l和r代表当前区间[l,r],若S(l,r)<s,则 r++。若S(l,r)≥s,则 l++,直至S(l,r)<s。如果当前S(l,r)<s且r=n则退出。输出最小区间长度[l,r]即可。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cmath>
 5 using namespace std;
 6 const int MAXN=100000+50;
 7 int num[MAXN],n,s;
 8 
 9 void solve()
10 {
11     scanf("%d%d",&n,&s);
12     for (int i=1;i<=n;i++) scanf("%d",&num[i]);
13     int l=1,r=1,sum=num[1],len=MAXN;
14     for (;;)
15     {
16         if (sum>=s)
17         {
18             len=min(len,r-l+1);
19             sum-=num[l++];
20         }
21         else
22         {
23             if (r==n) break;
24             sum+=num[++r];
25         }
26     }
27     if (len==MAXN) puts("0");
28         else printf("%d\n",len);
29 }
30 
31 int main()
32 {
33     int T;
34     scanf("%d",&T);
35     while (T--)    solve();    
36     return 0;
37 }

 

POJ3320-Jessica‘s Reading Problem

【题目大意】

一个序列ai,其中ai可能相同。求最短的连续子序列长度,使得该子序列中包含所有的ai。

【思路】

由于ai可能非常大,先对ai进行离散化。用appear[a[i]]表示当前a[i]出现的次数。然后利用尺取法,sum表示当前区间中包含了几种不同的数,如果l右移而appear[a[l]]变为0则sum--,如果r右移而appear[a[r]]变为1则sum++。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 const int MAXN=1e6+5;
 8 int appear[MAXN],p,a[MAXN],hash[MAXN],d;
 9 
10 void init()
11 {
12     scanf("%d",&p);
13     for (int i=1;i<=p;i++) scanf("%d",&a[i]),hash[i]=a[i];
14     sort(hash+1,hash+p+1);
15     d=unique(hash+1,hash+p+1)-(hash+1);
16     for (int i=1;i<=p;i++) a[i]=lower_bound(hash+1,hash+d+1,a[i])-hash;
17 }
18 
19 void solve()
20 {
21     memset(appear,0,sizeof(appear));
22     appear[a[1]]=1;
23     int l=1,r=1,sum=1,ans=MAXN;
24     for (;;)
25     {    
26         if (sum>=d)
27         {
28             ans=min(ans,(r-l+1));
29             appear[a[l]]--;
30             if (!appear[a[l++]]) sum--;
31         }
32         else
33         {
34             if (r==p) break;
35             appear[a[r+1]]++;
36             if (appear[a[++r]]==1) sum++;
37         }
38     }
39     printf("%d",ans);
40 }
41 
42 int main()
43 {
44     init();
45     solve();
46     return 0;
47 }

 

【尺取法】POJ3061 & POJ3320