题意:给出一个矩阵 和a b   维护该矩阵包含的所有 a行b列子矩阵中的最小值 之和

 

用单调队列维护

div2574 E. OpenStreetMap 单调队列_单调队列

 

 

div2574 E. OpenStreetMap 单调队列_单调队列_02div2574 E. OpenStreetMap 单调队列_单调队列_03
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
typedef pair<ll,ll>pii;
//////////////////////////////////
const int N=3000+5;
 
ll ans;
ll mp[N][N],g[N*N],x,n,m,z,y,a,b,g0;
ll hang[N][N];
 
deque<pii>q;
void h(ll *s ,ll *ans)
{
   while(!q.empty())q.pop_back();
   rep(i,1,b)
   {
       while(!q.empty()&&q.back().first>s[i])q.pop_back();
       q.push_back(make_pair(s[i],i));
   }
   ans[1]=q.front().first;
   rep(i,2,m-b+1)
   {
       if(!q.empty()&&q.front().second<i)q.pop_front();
       while(!q.empty()&&q.back().first>s[i+b-1])q.pop_back();
       q.push_back(make_pair(s[i+b-1],i+b-1));
       ans[i]=q.front().first;
   }
}
void v(int x)
{
    while(!q.empty())q.pop_back();
 
    rep(i,1,a)
    {
        while(!q.empty()&&q.back().first>hang[i][x])q.pop_back();
        q.push_back(make_pair(hang[i][x],i));
    }
    mp[1][x]=q.front().first;
    rep(i,2,n-a+1)
    {
        if(!q.empty()&&q.front().second<i)q.pop_front();
        while(!q.empty()&&q.back().first>hang[i+a-1][x])q.pop_back();
        q.push_back(make_pair(hang[i+a-1][x],i+a-1));
        mp[i][x]=q.front().first;
    }
}
ll sol()
{
    scanf("%lld%lld%lld%lld",&n,&m,&a,&b);
    scanf("%lld%lld%lld%lld",&g0,&x,&y,&z);
    g[0]=g0;
    rep(i,1,n*m)g[i]=(g[i-1]*x+y)%z;
    rep(i,1,n)rep(j,1,m)mp[i][j]=g[(i-1)*m+j-1];
 
    rep(i,1,n)h(mp[i],hang[i]);
    rep(i,1,m)v(i);
 
    ll ans=0;
    rep(i,1,n-a+1)rep(j,1,m-b+1)
    ans+=mp[i][j];
 
    return ans;
}
 
int main(){ printf("%lld",sol()); }
 
 
View Code