【2020牛客暑期多校训练营(第二场)】F. Fake Maxpooling

知识点:单调队列

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 int n,m,k,head,tail;
 5 int a[5010][5010];
 6 int que[5010];
 7 int p[5010][5010]={0},h2,t2,qq[5010];
 8 long long ans=0;
 9 int gcd(int x,int y)
10 {
11     return y==0?x:gcd(y,x%y);
12 }
13 int main()
14 {
15     scanf("%d %d %d",&n,&m,&k);
16     for (int i=1;i<=n;i++)
17         for (int j=1;j<=m;j++)
18             a[i][j]=i/gcd(i,j)*j;
19     for (int j=1;j<=m;j++)
20     {
21         for (int i=1;i<=n;i++) qq[i]=0;
22         h2=t2=1;
23         for (int i=1;i<k;i++)
24         {
25             while (t2>=h2 && a[i][j]>a[qq[t2]][j]) t2--;
26             t2++;
27             qq[t2]=i;
28         }
29         for (int i=k;i<=n;i++)
30         {
31             while (t2>=h2 && i-qq[h2]>=k) h2++;
32             while (t2>=h2 && a[i][j]>a[qq[t2]][j]) t2--;
33             t2++;
34             qq[t2]=i;
35             p[i-k+1][j]=a[qq[h2]][j];
36         }
37     }
38 
39     for (int i=1;i<=n-k+1;i++)
40     {
41         for (int j=1;j<=m;j++) que[j]=0;
42         head=tail=1;
43         for (int j=1;j<k;j++)
44         {
45             while (tail>=head && p[i][j]>p[i][que[tail]]) tail--;
46             tail++;
47             que[tail]=j;
48         }
49         for (int j=k;j<=m;j++)
50         {
51             while (tail>=head && j-que[head]>=k) head++;
52             while (tail>=head && p[i][j]>p[i][que[tail]]) tail--;
53             tail++;
54             que[tail]=j;
55             ans+=p[i][que[head]];
56         }
57     }
58     printf("%lld\n",ans);
59     return 0;
60 }

 

posted @ 2020-07-13 19:28  Clair_R  阅读(70)  评论(0编辑  收藏  举报