您的位置:首页 > 其它

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

2020-07-15 14:38 423 查看

这个题目就是用一个二维单调队列,但是比赛的时候就是没有想到,更奇葩的是我居然连题目都读错了,读成了求在nm矩阵里找一个kk大小的使得这个kk的矩阵的值的和最大,而题目本来的意思是求每一个kk矩阵里面的最大值然后加起来,lcj做出来后说是二维单调队列我当时一脸懵逼,首先我是读错了题目,然后是二维单调队列没看见过,不知道长哪样,我还是太菜了。

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ull unsigned long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define lson num<<1
#define rson num<<1|1
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 2e5+ 50;
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;
const ll  lnf  = 0x3f3f3f3f3f3f3f3f;
const ll mod = 23333;
const  double pi=3.141592653589;
int a[5005][5005],n,m,k,ma[5005][5005];
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int q[5005];
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[i][j]=(i*j)/gcd(i,j);
}
}
for(int i=1;i<=n;i++)
{
int tail=0,head=0;
for(int j=1;j<=m;j++)
{
while(tail>head&&a[i][q[tail-1]]<=a[i][j])tail--;//使得队列是递增的
q[tail++]=j;
while(tail>head&&j-q[head]>=k)head++;//保证队列维护的是k这么大的区间,而且必须是等于,不然会wa到哭
ma[i][j]=a[i][q[head]];
}
}
ll ans=0;
for(int j=1;j<=m;j++)
{
int tail=0,head=0;
for(int i=1;i<=n;i++)
{
while(tail>head&&ma[q[tail-1]][j]<=ma[i][j])tail--;//看清楚了,这是ma是上一次求的这一行的最大值
q[tail++]=i;
while(tail>head&&i-q[head]>=k)head++;
if(j>=k&&i>=k)//这个一定要加,不然会连输出都不对
ans+=ma[q[head]][j];
}
}
printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: