zoukankan      html  css  js  c++  java
  • 图论+前缀和 任(duty)

    问题 B: 任(duty)
    时间限制: 2 Sec 内存限制: 512 MB
    题目描述
    liu_runda退役之后就失去梦想开始咸鱼生活了…
    Bilibili夏日画板活动中,所有人都可以在一块画板上进行像素画创作.UOJ群有一群无聊的人决定在画板上创作一个50*50的UOJ的LOGO.如下图.
    这块画板实际上是很大的矩形网格.一个网格是一像素.
    一个人每三分钟才能画一个像素.所以liu_runda的咸鱼生活非常无聊.
    郭神表示他实在是看不下去liu_rudna这只颓狗了,于是随手出了一道神题,liu_runda不会做,于是给出到联考里了.
    在画板上有一片黑白相间的矩形区域满足这样的性质:如果认为相同颜色的方块可以在上下左右四个方向连通,那么任意两个黑色方块要么不连通,要么连通但之间只有一条简单路径(不重复经过同一个格子的路径).
    这个矩形区域有N行M列,从上到下依次为第1,2,3…N-1,N行,从左到右依次为第1,2,3…M-1,M列.
    每次郭神会询问这片矩形区域内的一个子矩形.在只考虑这个子矩形内的像素时(即从子矩形内部不能和子矩形之外的像素相连通),问这个子矩形内的黑色方块组成了多少连通块.
    如果不能完成这个任务,liu_runda就会被郭神批判一番…
    【输入格式】

    第一行三个整数N,M,Q,表示矩形区域有N行M列,有Q组询问.

    接下来N行,每行一个长为M的01字符串.0表示白色,1表示黑色.第i行第j个字符表示第i行j列的颜色,

    接下来Q行,每行4个整数x1,y1,x2,y2,(x1<=x2,y1<=y2)表示选出的矩形区域的两个对角.即选出一个左上角为第x1行第y1列,右下角为第x2行第y2列,包含x2-x1+1行,y2-y1+1列的区域.

    【输出格式】

    Q行,第i行一个整数ans表示第i组询问的答案.

    【样例输入1】

    3 4 4

    1101

    0110

    1101

    1 1 3 4

    1 1 3 1

    2 2 3 4

    1 2 2 4

    【样例输出1】

    3

    2

    2

    2

    【样例输入2】

    5 5 6

    11010

    01110

    10101

    11101

    01010

    1 1 5 5

    1 2 4 5

    2 3 3 4

    3 3 3 3

    3 1 3 5

    1 1 3 4

    【样例输出2】

    3

    2

    1

    1

    3

    2

    【数据范围】

    对于第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,保证任意两个黑色像素之间最多只有一条简单路径.

    其实题面里还有张很无聊的图,懒得粘了。。
    因为保证联通块里不存在环,只能由一条边互相连通,而同一联通块满足点数-边数==1;所以求出区间里所有点和所有边,相减即为答案。
    因此我们可以维护前缀和。但有些细节。
    举个样例(为了方便说我把0,1改成了点的标号)
    1 2 3 4
    5 6 7 8
    9 0 10 11
    比如我们要求7,8,10,11的,那么要把3-7,4-8,6-7,0-10的边都剪掉,因此会多剪掉7-10和7-8,所以得额外维护单列的值,把它加回去,具体就不细说了。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define N 2005
    #define inf 1000000000
    using namespace std;
    int read()
    {
        int sum=0,f=1;char x=getchar();
        while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
        while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}
        return sum*f;
    }
    int n,m,q;
    int a[2005][2005],dian[2005][2005],bian[2005][2005],h[2005][2005],z[2005][2005];
    int l1,l2,r1,r2;
    void init()
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                dian[i][j]=dian[i][j-1]+a[i][j];
                bian[i][j]=bian[i][j-1];
                if(a[i][j]==1&&a[i][j-1]==1)bian[i][j]++;
                h[i][j]=bian[i][j];
            }
        for(int j=1;j<=m;j++)
            for(int i=1;i<=n;i++)
            {
                dian[i][j]+=dian[i-1][j];
                z[i][j]=z[i-1][j];
                if(a[i][j]==1&&a[i-1][j]==1)z[i][j]++;
            }
        for(int i=1;i<=n;i++)
        {
            int s=0;
            for(int j=1;j<=m;j++)
            {
                if(a[i][j]==1&&a[i-1][j]==1)s++;
                bian[i][j]+=bian[i-1][j]+s;
            }
        }
    /*  for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                cout<<z[i][j]<<" ";
            cout<<endl;
        }*/
    }
    int main()
    {
        n=read();m=read();q=read();
        char s[2005];
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            for(int j=1;j<=m;j++)
                a[i][j]=s[j]-'0';
        }
        init();int ans2,ans1;
        while(q--)
        {
            l1=read();r1=read();l2=read();r2=read();
            ans1=dian[l2][r2]-dian[l2][r1-1]-dian[l1-1][r2]+dian[l1-1][r1-1];
            ans2=bian[l2][r2]-bian[l2][r1]-bian[l1][r2]+bian[l1][r1];
            ans2+=z[l2][r1]-z[l1][r1]+h[l1][r2]-h[l1][r1];
            //cout<<ans1<<" "<<ans2<<endl;
            printf("%d
    ",ans1-ans2);
        }
    }
  • 相关阅读:
    [cf553C]Love Triangles
    Unix目录结构的来历
    debian学习笔记9, putty连接debian的字体乱码修改设置。
    【转】Dictionary排序
    debian学习笔记9, putty连接debian的字体乱码修改设置。
    【转】可以用圆形的钻头钻出方孔吗
    【转】Dictionary排序
    关于设置sftp 指定端口
    【转】可以用圆形的钻头钻出方孔吗
    Unix目录结构的来历
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632653.html
Copyright © 2011-2022 走看看