zoukankan      html  css  js  c++  java
  • 【图论前缀和 技巧】任

    有趣的二维前缀和

    题目描述 = 略

    题目大意

    一个用01矩阵表示的图中,如果两个1号格子相邻则表示它们相互连通,其中保证连通的1号格子无环存在。每一次询问一个子矩阵中的连通块个数。

    对于第 1,2 个测试点,Q=1
    对于第 3,4 个测试点,N=1
    对于第 5,6,7 个测试点,N=2
    对于第 8 个测试点,N,M<=1000
    对于第 9 个测试点,N,M<=1500

    对于全部测试点,1<=N,M<=2000,1<=Q<=200000,1<=x1<=x2<=N,1<=y1<=y2<=M


    题目分析

    基础暴力做法

    本题的部分分给的还是非常良心的。我们可以试一试对于每一次的询问都做一次洪水填充。那么复杂度大概是O(nmq)的。

    要注意一点,如果每一次询问时都把vis数组memset,会TLE得只剩20分。我们只要每一次染不同的颜色就好了。

     1 #include<bits/stdc++.h>
     2 const int maxn = 2003;
     3 const int dx[] = {0, 1, 0, -1, 0};
     4 const int dy[] = {0, 0, 1, 0, -1};
     5 
     6 int n,m,q,a,b,c,d;
     7 int mp[maxn][maxn];
     8 int vis[maxn][maxn];
     9 
    10 inline int getint()
    11 {
    12     char ch = getchar();
    13     for (; !isdigit(ch); ch = getchar());
    14     return ch-'0';
    15 }
    16 inline int read()
    17 {
    18     int num = 0;
    19     char ch = getchar();
    20     for (; !isdigit(ch); ch = getchar());
    21     for (; isdigit(ch); ch = getchar())
    22         num = (num<<1)+(num<<3)+ch-48;
    23     return num;
    24 }
    25 void dfs(int x, int y, int col)
    26 {
    27     if (x < a || x > c || y < b || y > d || vis[x][y]==col || !mp[x][y]) return;
    28     vis[x][y] = col;
    29     for (int i=1; i<=4; i++)
    30         dfs(x+dx[i], y+dy[i], col);
    31 }
    32 int main()
    33 {
    34     n = read(), m = read(), q = read();
    35     register int ans,i,j,k;
    36     for (i=1; i<=n; i++)
    37         for (j=1; j<=m; j++)
    38             mp[i][j] = getint();
    39     for (i=1; i<=q; i++)
    40     {
    41         a = read(), b = read(), c = read(), d = read();
    42         ans = 0;
    43         for (j=a; j<=c; j++)
    44             for (k=b; k<=d; k++)
    45                 if (vis[j][k]!=i && mp[j][k])
    46                     dfs(j, k, i),ans++;
    47         printf("%d
    ",ans);
    48     }
    49     return 0;
    50 }

    期望得分 = 实际得分 = 70分。

    要一些结论的做法

    这种题型————二维的计数问题————大概算是一种套路吧。我们考虑一下二维的前缀和。

    仔细观察一下(虽然这挺不显然的),会发现对于无环图,一个矩形区域内的连通块个数=点数-边数

    诶,那么有了这个性质再二维前缀和就非常方便了。

    注意横边和竖边是要分开保存的。

    一开始我非常奇怪为什么边不保存在一起。后来发现是因为:相同一个区域内的横边和竖边,在数组中保存的二维区间是不一样的。

     1 #include<bits/stdc++.h>
     2 const int maxn = 2003;
     3 
     4 int f[maxn][maxn],mp[maxn][maxn];
     5 int egs1[maxn][maxn],egs2[maxn][maxn];
     6 int n,m,q;
     7 
     8 inline int getint()
     9 {
    10     char ch = getchar();
    11     for (; !isdigit(ch); ch = getchar());
    12     return ch-'0';
    13 }
    14 inline int read()
    15 {
    16     char ch = getchar();
    17     int num = 0;
    18     for (; !isdigit(ch); ch = getchar());
    19     for (; isdigit(ch); ch = getchar())
    20         num = (num<<1)+(num<<3)+ch-48;
    21     return num;
    22 }
    23 int main()
    24 {
    25     n = read(), m = read(), q = read();
    26     for (int i=1; i<=n; i++)
    27         for (int j=1; j<=m; j++)
    28             mp[i][j] = getint(),f[i][j] = f[i-1][j]+f[i][j-1]-f[i-1][j-1]+mp[i][j];
    29     for (int i=1; i<=n; i++)
    30         for (int j=1; j<=m; j++)
    31         {
    32             egs1[i][j] = egs1[i-1][j]+egs1[i][j-1]-egs1[i-1][j-1];
    33             egs2[i][j] = egs2[i-1][j]+egs2[i][j-1]-egs2[i-1][j-1];
    34             if (!mp[i][j]) continue;
    35             if (mp[i][j-1]) egs1[i][j]++;
    36             if (mp[i-1][j]) egs2[i][j]++;
    37         }
    38     for (int i=1; i<=q; i++)
    39     {
    40         int a = read(), b = read(), c = read(), d = read();
    41         int ans = f[c][d]+f[a-1][b-1]-f[a-1][d]-f[c][b-1];
    42         ans -= egs1[c][d]+egs1[a-1][b]-egs1[a-1][d]-egs1[c][b];      //这里,可以看到横边和竖边的操作是不同的。
    43         ans -= egs2[c][d]+egs2[a][b-1]-egs2[a][d]-egs2[c][b-1];
    44         printf("%d
    ",ans);
    45     }
    46     return 0;
    47 } 

    END

  • 相关阅读:
    好多天没写了,郁闷
    昨天很受教育
    恼火的服务器
    欢迎访问我的博客网站
    体育产品论坛
    参考书目
    web2.0与数字标准
    用户产生内容与网站做内容
    Using x++ code reading data from csv file format
    Find out specified the folder for all the files
  • 原文地址:https://www.cnblogs.com/antiquality/p/8997616.html
Copyright © 2011-2022 走看看