luoguP6070 [MdOI2020] Decrease 贪心+二维差分

显然从左到右,从上到下依次处理每个格子步数是最少的.        

而由于我们的顺序是固定的,每次操作等于是一个区间修改,单点查询.  

利用二维差分的方式可以轻松实现. 

code: 

#include <cstdio>  
#include <cstring> 
#include <string> 
#include <vector>
#include <algorithm> 
#define N 5003        
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std; 
ll mat[N][N],sum[N][N],det[N][N];
int main() 
{ 
    // setIO("input");  
    int i,j,n,m,k;   
    scanf("%d%d%d",&n,&m,&k);     
    for(i=1;i<=m;++i) 
    {
        int x,y,z;  
        scanf("%d%d%d",&x,&y,&z),mat[x][y]+=z;   
    }      
    ll ans=0;                     
    for(i=1;i<=n;++i) 
    {
        for(j=1;j<=n;++j) 
        {              
            sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];      
            if(i+k-1<=n&&j+k-1<=n) 
            { 
                ll cur=mat[i][j]+sum[i][j];        
                ans+=abs(cur);                                 
                sum[i][j]-=cur;       
                sum[i+k][j]+=cur;   
                sum[i][j+k]+=cur;    
                sum[i+k][j+k]-=cur; 
            }  
        }
    }              
    int flag=1;     
    for(i=1;i<=n;++i) 
    {
        for(j=1;j<=n;++j) if(mat[i][j]+sum[i][j]) flag=0; 
    } 
    printf("%lld\n",flag?ans:-1);   
    return 0;
}

  

posted @ 2020-02-13 16:37  EM-LGH  阅读(229)  评论(0编辑  收藏  举报