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