2020暑期第二场 Fake Maxpooling(单调队列)

const int N = 5005;
int t;
struct node
{
    ll idx, w;
}q[N];
vector<int> v[N];
int main()
{
    //freopen("in.txt", "r", stdin);
    int n, m, k;
    cin >> n >> m >> k;
    //f(i, 1, n)f(j, 1, m)mp[i][j] = i * j / gcd(i, j);
    //单调队列k长度区间最值
    f(i, 1, n)//水平方向求一遍单调队列
    {
        int tail = 0, head = 0;
        f(j, 1, m)
        {
            ll lcm = (ll)i*j / gcd(i, j);
            while (head<tail &&lcm > q[tail-1].w)//维护递减序列
                tail--;//把比当前小,而且老的信息删除
            q[tail++] = { j,lcm };
            while (head<tail&& j - q[head].idx + 1 > k)head++;
            //删去过期信息
            if (j >= k)v[i].emplace_back(q[head].w);
        }
    }
    ll ans = 0;
    f(i, 0,(int) v[1].size()-1)//竖直方向跑一遍
    {
        int tail = 0, head = 0;
        f(j, 1, n)
        {
            while (head<tail && v[j][i]> q[tail-1].w)//维护递减序列
                tail--;//把比当前小,而且老的信息删除
            q[tail++] = { j,v[j][i] };
            while (head<tail && j - q[head].idx + 1 > k)head++;
            //删去过期信息
            if (j >= k)ans += q[head].w;
        }
    }
    cout << ans << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值