zoukankan      html  css  js  c++  java
  • 01矩阵系列(计数/最大查询)

    51Nod 1291

    题意:600*600的01矩阵,统计宽i高j的全1矩阵的个数。

    题解:枚举矩阵的下边界,对于每个下边界,统计所有宽极大的矩形的答案(高度可以用差分)。O(nm)的复杂度统计完之后,我们已知所有高度的宽极大的答案,列一下式子发现两次前缀和就是最后答案。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define st first
     4 #define nd second
     5 #define rep(i, a, b) for(int i=(a); i<(b); i++)
     6 #define sz(x) (int)x.size()
     7 #define de(x) cout<< #x<<" = "<<x<<endl
     8 #define dd(x) cout<< #x<<" = "<<x<<" "
     9 typedef long long ll;
    10 typedef pair<int, int> pii;
    11 typedef vector<int> vi;
    12 
    13 const int N = 666;
    14 int n, m, top;
    15 int u[N], sta[N];
    16 ll c[N][N];
    17 char s[N];
    18 
    19 int main() {
    20     scanf("%d%d", &n, &m);
    21     for(int i = 1; i <= n; i++) {
    22         scanf("%s", s+1);
    23         for(int j = 1; j <= m; j++)
    24             u[j] = (s[j] == '1')? u[j]+1: 0;
    25         top = 0;
    26         sta[top++]=0;
    27         for(int j = 1; j <= m+1; j++) {
    28             while(u[sta[top-1]] > u[j]) {
    29                 ++c[max(u[sta[top-2]], u[j])+1][j-sta[top-2]-1];//维护单调上升的栈, 看每个柱块向左和向右的最大延伸距离, 即为宽度
    30                 --c[u[sta[top-1]]+1][j-sta[top-2]-1];            //枚举i为底边, 对高度范围为[max(u[sta[top-2]],u[j])+1, u[sta[top-1]]], 宽度为j-sta[top-2]-1的矩形加1
    31                 --top;
    32             }
    33             while(top && u[sta[top-1]] == u[j]) --top;
    34             sta[top++] = j;
    35         }
    36     }
    37     for(int i = 2; i <= n; i++) for(int j = 1; j <= m; j++) c[i][j] += c[i-1][j]; //c1[i, j]: 高为i (n^2) 的连通块, 只统计最长宽度的。
    38     for(int i = 1; i <= n; i++) {
    39         for(int j = m-1; j; j--) c[i][j] += c[i][j+1];    //c2[i, j]: 高i宽 >= j的连通块的个数
    40         for(int j = m-1; j; j--) c[i][j] += c[i][j+1];  //c3[i, j]: 高i宽j的全1矩阵的个数
    41     }
    42     for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) printf("%lld%c", c[i][j], " 
    "[j == m]);
    43     return 0;
    44 }
    45 /*
    46 3 3
    47 011
    48 110
    49 110
    50 如何得到c1? 暴力的话, c1是枚举n^2的上下边界, 优化后, 变成枚举直方图的最底边,快速统计各个不同的上顶边。这个可以通过单调栈+差分解决。求前缀和后就得到c1。
    51 总的时间复杂度为O(nm).
    52 c1
    53 0 3 0
    54 1 1 0
    55 1 0 0
    56 c2
    57 3 3 0
    58 2 1 0
    59 1 0 0
    60 c3
    61 6 3 0
    62 3 1 0
    63 1 0 0
    64 
    65 */

    Wannafly挑战赛12 D

    题意:1e9*1e9的01矩阵,1的个数c个(c <= 5000),统计全0矩阵的个数。

    题解:所有情况 减去 包含1的。包含1的矩阵这么算:对于每个1,统计包含这个1而不包含之前的1的矩阵个数。思想类似于带禁手的马跳棋盘方案数计数。时间复杂度 O(c^2)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define st first
     4 #define nd second
     5 typedef long long ll;
     6 const int mod = 1e9+7;
     7 pair<int, int> s[5111];
     8 int main() {
     9     int n, m, c;
    10     scanf("%d%d%d", &n, &m, &c);
    11     for(int i = 1, x, y; i <= c; i++) scanf("%d%d", &x, &y), s[i] = {x, y};
    12     sort(s+1, s+c+1);
    13     long long ans = 0;
    14     for(int i = 1; i <= c; i++){
    15         int l = 0, r = m+1;
    16         for(int j = i-1; ~j; j--){                                                            //从下往上从左往右枚举之前的点
    17             ans += (r-s[i].nd)*(n-s[i].st+1LL)%mod*(s[j+1].st-s[j].st)%mod*(s[i].nd-l)%mod;    //上边界为s[j].st ~ s[j+1].st
    18             ans %= mod;
    19             if(s[j].nd > s[i].nd) r = min(r, s[j].nd);
    20             if(s[j].nd < s[i].nd) l = max(l, s[j].nd);
    21         }
    22     } 
    23     //n*m矩阵的子矩阵个数 = 左右两边界 * 上下两边界 
    24     long long cnt = (n*(n+1LL)/2%mod)*(m*(m+1LL)/2%mod)%mod;
    25     ans = (cnt-ans)%mod;
    26     if(ans < 0) ans += mod;
    27     printf("%lld
    ", ans);
    28     return 0;
    29 }

    Codeforces 713D Animals and Puzzle

    题意:一个n*m的01矩阵,Q个询问,每次询问一个矩形区域内,最大的全1正方形的边长是多少?

    题解:dp[0][0][i][j]表示以(i, j)为右下角的正方形的最长边长。RMQ后,二分答案即可。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 using namespace std;
     5 typedef long long ll;
     6 const int N = 1e3+10;
     7 int x1, y1, x2, y2, n, m;
     8 int a[N][N];
     9 int dp[10][10][N][N];
    10 int Log[N];
    11 int ask(int x1, int y1, int x2, int y2){
    12     int k1 = Log[x2-x1+1], k2 = Log[y2-y1+1];
    13     int ans = max(dp[k1][k2][x1][y1], dp[k1][k2][x1][y2-(1<<k2)+1]);
    14     ans = max(ans, dp[k1][k2][x2-(1<<k1)+1][y1]);
    15     ans = max(ans, dp[k1][k2][x2-(1<<k1)+1][y2-(1<<k2)+1]);
    16     return ans;
    17 }
    18 bool test(int l){
    19     //dp[0][x1][y1] dp[0][x2-x+1][y2-x+1]
    20     int ret = ask(x1+l-1, y1+l-1, x2, y2);
    21     return ret >= l;
    22 }
    23 void init(){
    24     for(int i = 1; i <= Log[n]; i++)
    25         for(int x = 1; x+(1<<i)-1 <= n; x++)
    26             for(int y = 1; y <= m; y++)
    27                 dp[i][0][x][y] = max(dp[i-1][0][x][y], dp[i-1][0][x+(1<<i-1)][y]);
    28     for(int i = 0; i <= Log[n]; i++)
    29         for(int j = 1; j <= Log[m]; j++)
    30             for(int x = 1; x+(1<<i)-1 <= n; x++)
    31                 for(int y = 1; y+(1<<j)-1 <= m; y++)
    32                     dp[i][j][x][y] = max(dp[i][j-1][x][y], dp[i][j-1][x][y+(1<<j-1)]);
    33 }
    34 int main(){
    35     for(int i = 2; i < N; i++) Log[i] = Log[i>>1]+1;
    36     scanf("%d%d", &n, &m);
    37     for(int i = 1; i <= n; i++)
    38         for(int j = 1; j <= m; j++){
    39             scanf("%d", &a[i][j]);
    40             if(a[i][j] == 0) dp[0][0][i][j] = 0;
    41             else{
    42                 int len = min(dp[0][0][i-1][j], dp[0][0][i][j-1]);
    43                 dp[0][0][i][j] = len+a[i-len][j-len];
    44             }
    45         }
    46     init();
    47 
    48     int t; scanf("%d", &t);
    49     while(t--){
    50         scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
    51         int L = 0, R = min(x2-x1+1, y2-y1+1);
    52         while(L < R){
    53             int M = L+R+1 >> 1;
    54             if( test(M) )
    55                 L = M;
    56             else
    57                 R = M-1;
    58         }
    59         printf("%d
    ", L);
    60     }
    61     return 0;
    62 }
    View Code
  • 相关阅读:
    English Training Material
    SingleThreadModel is deprecated in Servlet API version 2.4
    What is the difference Apache (Http Server) and Tomcat (Servlet Container)
    Add a stylesheet link programmatically in ASP.NET
    Detail in Response.redirect and Server.transfer in ASP.NET
    @font-face usage
    实习面试总结(只写了昨天腾讯的面试和拿到offer的一个小公司, 有空再把前面的补上吧)
    redis-cli启动问题
    关于结构体内存对齐
    memcpy 和 memmove
  • 原文地址:https://www.cnblogs.com/dirge/p/10034268.html
Copyright © 2011-2022 走看看