zoukankan      html  css  js  c++  java
  • HDU 5749 Colmerauer 单调队列+暴力贡献

    BestCoder Round #84   1003

    分析:(先奉上zimpha巨官方题解)

    感悟:看到题解单调队列,秒懂如何处理每个点的范围,但是题解的一句算贡献让我纠结半天

            已知一个点的up,down,left,right,即上下左右的扩展范围,如何确定贡献呢

            其实也很好做,把所有可能的矩形的长算出来,得到和,宽也是一样,然后乘法原理乘起来就好

    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    #include <string.h>
    #include <vector>
    #include <math.h>
    #include <stack>
    #include <map>
    using namespace std;
    typedef long long LL;
    const int N = 1e3+5;
    const int INF = 0x3f3f3f3f;
    const LL mod = 1ll<<32;
    int a[N][N],l[N][N],r[N][N],u[N][N],d[N][N];
    int T,n,m;
    stack<int>s;
    LL cal(LL x,LL y){
      return (x*(x+1)/2*y%mod+y*(y-1)/2*x%mod)%mod; 
    }
    int main(){
      scanf("%d",&T);
      while(T--){
         scanf("%d%d",&n,&m);
         for(int i=1;i<=n;++i)
          for(int j=1;j<=m;++j)
            scanf("%d",&a[i][j]);
         for(int i=1;i<=n;++i){
            a[i][m+1]=a[i][0]=-INF;
            while(!s.empty())s.pop();s.push(0);
            for(int j=1;j<=m;++j){
              while(!s.empty()&&a[i][s.top()]>a[i][j])s.pop();
              l[i][j]=s.top();s.push(j);
            }
            while(!s.empty())s.pop();s.push(m+1);
            for(int j=m;j;--j){
              while(!s.empty()&&a[i][s.top()]>a[i][j])s.pop();
              r[i][j]=s.top();s.push(j);
            }
         }
         for(int j=1;j<=m;++j){
           a[0][j]=a[n+1][j]=INF;
           while(!s.empty())s.pop();s.push(0);
           for(int i=1;i<=n;++i){
            while(!s.empty()&&a[s.top()][j]<a[i][j])s.pop();
            u[i][j]=s.top();s.push(i);
           }
           while(!s.empty())s.pop();s.push(n+1);
           for(int i=n;i;--i){
             while(!s.empty()&&a[s.top()][j]<a[i][j])s.pop();
             d[i][j]=s.top();s.push(i);
           }
         }
         LL ret=0;
         for(int i=1;i<=n;++i)
          for(int j=1;j<=m;++j){
            LL curl=j-l[i][j],curr=r[i][j]-j;
            LL curu=i-u[i][j],curd=d[i][j]-i;
            ret+=cal(curl,curr)*cal(curu,curd)%mod*a[i][j]%mod;
            ret%=mod;
          }
         printf("%I64d
    ",ret);
      }
      return 0;
    }
    View Code
  • 相关阅读:
    tuple-1
    禅语-1
    综述的写作技巧-1
    皆大欢喜组合
    类和对象-3
    双棍练习
    CodeBlocks开发环境使用-1
    类和对象-2
    类和对象-1
    13-归并排序-分治策略应用于排序
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5700975.html
Copyright © 2011-2022 走看看