• BZOJ1047 [HAOI2007]理想的正方形


    昨天刷水累死蒟蒻了。。。

    每天一到题解总还是要写的。。。于是就是这个了!

    二维RMQ,第一反应是二维线段树,妥妥MLE + TLE

    想起来去年市选小题有一道一模一样的,我当时就是写二维线段树,然后MLE0分、、、真是悲剧

    发现长度是固定的为n,和动态规划的某个叫单调队列的优化很像:

    先求出每一列的某个点向下n个数的最大/小值,然后求出每一行某个点向右的n个单调队列的最大/小值,方法依旧是单调队列。。。

    程序写的很烦。。。是照抄网上的。。。(太烦了不想写呢><)

     1 /**************************************************************
     2     Problem: 1047
     3     User: rausen
     4     Language: C++
     5     Result: Accepted
     6     Time:1604 ms
     7     Memory:16600 kb
     8 ****************************************************************/
     9  
    10 #include <cstdio>
    11 #include <algorithm>
    12  
    13 using namespace std;
    14 const int N = 1005;
    15  
    16 int mp[N][N];
    17 int q[N][N], h[N], t[N], Q[N];
    18 int mx[N][N], mn[N][N];
    19 int s, e, a, b, n;
    20  
    21 inline int read(){
    22     int x = 0, sgn = 1;
    23     char ch = getchar();
    24     while (ch < '0' || ch > '9'){
    25         if (ch == '-') sgn = -1;
    26         ch = getchar();
    27     }
    28     while (ch >= '0' && ch <= '9'){
    29         x = x * 10 + ch - '0';
    30         ch = getchar();
    31     }
    32     return sgn * x;
    33 }
    34  
    35 void getmax(){
    36     for (int i = 1; i <= b; ++i)
    37         h[i] = 1, t[i] = 0;
    38     for (int i = 1; i <= a; ++i){
    39         for (int j = 1; j <= b; ++j){
    40             while (h[j] <= t[j] && i - q[j][h[j]] >= n) ++h[j];
    41             while (h[j] <= t[j] && mp[q[j][t[j]]][j] <= mp[i][j]) --t[j];
    42             q[j][++t[j]] = i;
    43         }
    44         e = 0, s = 1;
    45         for (int j = 1; j <= b; ++j){
    46             while (s <= e && j - Q[s] >= n) ++s;
    47             while (s <= e && mp[q[Q[e]][h[Q[e]]]][Q[e]] <= mp[q[j][h[j]]][j]) --e;
    48             Q[++e] = j;
    49             mx[i][j] = mp[q[Q[s]][h[Q[s]]]][Q[s]];
    50         }
    51     }
    52 }
    53  
    54 void getmin(){
    55     for (int i = 1; i <= b; ++i)
    56         h[i] = 1, t[i] = 0;
    57     for (int i = 1; i <= a; ++i){
    58         for (int j = 1; j <= b; ++j){
    59             while (h[j] <= t[j] && i - q[j][h[j]] >= n) ++h[j];
    60             while (h[j] <= t[j] && mp[q[j][t[j]]][j] >= mp[i][j]) --t[j];
    61             q[j][++t[j]] = i;
    62         }
    63         e = 0, s = 1;
    64         for (int j = 1; j <= b; ++j){
    65             while (s <= e && j - Q[s] >= n) ++s;
    66             while (s <= e && mp[q[Q[e]][h[Q[e]]]][Q[e]] >= mp[q[j][h[j]]][j]) --e;
    67             Q[++e] = j;
    68             mn[i][j] = mp[q[Q[s]][h[Q[s]]]][Q[s]];
    69         }
    70     }
    71 }
    72  
    73 int main(){
    74     a = read(), b = read(), n = read();
    75     for (int i = 1; i <= a; ++i)
    76         for (int j = 1; j <= b; ++j)
    77             mp[i][j] = read();
    78      
    79     getmax();
    80     getmin();
    81     int ans = (int) 1e9;
    82     for (int i = n; i <= a; ++i)
    83         for (int j = n; j <= b; ++j)
    84             ans = min(ans, mx[i][j] - mn[i][j]);
    85     printf("%d
    ", ans);
    86     return 0;
    87 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    ###第五次作业###
    第四次作业
    第三次作业
    jquery cookie插件
    jquery.form.js(ajax表单提交)
    jquery 中 $.map 用法
    jQuery中的$.grep()使用
    jquery-validation验证插件
    软件工程实践2017第一次作业
    jQuery UI dialog 的使用
  • 原文地址:https://www.cnblogs.com/rausen/p/4038937.html
Copyright © 2020-2023  润新知