zoukankan      html  css  js  c++  java
  • TZOJ 3042 切蛋糕(并查集)

    描述

    KK是个心灵手巧的好姑娘,她做了一个大蛋糕请她的好朋友们来品尝。
    这个蛋糕分成n×n个正方形小格,每个小格包含一块水果。KK要把蛋糕切成若干块,显然她不会破坏任意一个小格。
    无聊的某同学在她切蛋糕时不停地问她同一种问题:某两个小格是否还在同一块蛋糕里?
    例如下图中,KK从(1,1)切到(4,1),又从(1,1)切到(1,4),从而将蛋糕分成了两块。然后又从(2,1)切到(2,3),从(1,3)切到(2,3),于是把整个蛋糕分成了三块。其中小格(2,2)只和小格(2,3)连通,与其它所有小格不连通。

    KK被这些无聊的问题烦透了,她请求你编写一个程序让他闭嘴。

    输入

    输入包括多组数据。
    每组数据第一行为两个整数:蛋糕大小n (1≤n≤1000),以及KK切蛋糕次数和问题数之和q (1≤q≤100000)
    然后q行,每行是下面两者之一,描述了切蛋糕和问问题的过程:

    • cut x1 y1 x2 y2
      沿着坐标(x1,y1)和(x2,y2)连成的直线段切割蛋糕。
      输入数据确保x1=x2和y1=y2恰有其一成立,坐标(x1,y1)和(x2,y2)连成的直线段一定在蛋糕内部,并且KK不会重复切同一位置。
    • query x1 y1 x2 y2
      询问格子(x1,y1)和(x2,y2)是否在同一块蛋糕上(1≤x1, y1, x2, y2≤n)
    输入数据以n=q=0结束。

    输出

    对于输入数据中的query问题,如果两个格子在同一块蛋糕上则输出”Yes”,否则输出”No”。

    样例输入

    4 11
    query 1 1 2 2
    cut 1 1 4 1
    cut 1 1 1 4
    query 1 1 2 2
    query 2 2 3 3
    cut 2 3 2 1
    query 2 2 3 3
    cut 1 3 2 3
    query 2 2 3 3
    query 2 2 2 3
    query 1 1 2 4
    1000 1
    query 1 1 1000 1000
    0 0

    样例输出

    Yes
    No
    Yes
    Yes
    No
    Yes
    No
    Yes

    题意

    每次切一条线段,查询两块蛋糕是否被切开。

    题解

    相当于相邻蛋糕用边相连,然后删除一些边,询问是否连通。

    只有删边操作,那么可以考虑并查集,因为并查集是加边操作,所以可以把问题倒过来。

    每次加入并查集一条最后删掉的边。

    并查集路径压缩和按秩合并均摊O(1)。

    总时间复杂度O(n^2+q)。

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int N=1e6+5;
     5 const int M=1e5+5;
     6 int f[N],d[N];
     7 bool g[1005][1005][2],ans[M];
     8 int dx[]={1,0};
     9 int dy[]={0,1};
    10 int n;
    11 struct node
    12 {
    13     bool f;int x1,y1,x2,y2;
    14 }q[M];
    15 void init(int n)
    16 {
    17     for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)for(int k=0;k<2;k++)g[i][j][k]=1;
    18     int n1=n*n;for(int i=1;i<=n1;i++)d[i]=0,f[i]=i;
    19 }
    20 int F(int x){return f[x]==x?x:F(f[x]);}
    21 void merge(int x1,int y1,int x2,int y2)
    22 {
    23     int x=(x1-1)*n+y1,y=(x2-1)*n+y2;
    24     x=F(x),y=F(y);
    25     if(x==y)return;
    26     if(d[x]==d[y])d[x]++;
    27     if(d[x]<d[y])swap(x,y);
    28     f[y]=x;
    29 }
    30 int main()
    31 {
    32     int Q;char s[7];
    33     while(scanf("%d%d",&n,&Q)!=EOF,n||Q)
    34     {
    35         init(n);
    36         for(int i=1;i<=Q;i++)
    37         {
    38             scanf("%s%d%d%d%d",s,&q[i].y1,&q[i].x1,&q[i].y2,&q[i].x2);
    39             if(s[0]=='q')q[i].f=1;
    40             else
    41             {
    42                 q[i].f=0;
    43                 if(q[i].x1==q[i].x2)
    44                 {
    45                     if(q[i].x1==n)continue;
    46                     if(q[i].y1>q[i].y2)swap(q[i].y1,q[i].y2);
    47                     for(int j=q[i].y1+1;j<=q[i].y2;j++)g[q[i].x1][j][0]=0;
    48                 }
    49                 else
    50                 {
    51                     if(q[i].y1==n)continue;
    52                     if(q[i].x1>q[i].x2)swap(q[i].x1,q[i].x2);
    53                     for(int j=q[i].x1+1;j<=q[i].x2;j++)g[j][q[i].y1][1]=0;
    54                 }
    55             }
    56         }
    57         for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
    58         {
    59             for(int k=0;k<2;k++)
    60                 if(g[i][j][k]&&i+dx[k]<=n&&j+dy[k]<=n)
    61                     merge(i,j,i+dx[k],j+dy[k]);
    62         }
    63         for(int i=Q;i>=1;i--)
    64         {
    65             if(q[i].f)//query
    66             {
    67                 if(F((q[i].x1-1)*n+q[i].y1)==F((q[i].x2-1)*n+q[i].y2))ans[i]=1;
    68                 else ans[i]=0;
    69             }
    70             else//cut
    71             {
    72                 if(q[i].x1==q[i].x2)
    73                 {
    74                     if(q[i].x1==n)continue;
    75                     for(int j=q[i].y1+1;j<=q[i].y2;j++)
    76                         merge(q[i].x1,j,q[i].x1+1,j);
    77                 }
    78                 else
    79                 {
    80                     if(q[i].y1==n)continue;
    81                     for(int j=q[i].x1+1;j<=q[i].x2;j++)
    82                         merge(j,q[i].y1,j,q[i].y1+1);
    83                 }
    84             }
    85         }
    86         for(int i=1;i<=Q;i++)if(q[i].f)printf("%s
    ",ans[i]?"Yes":"No");
    87     }
    88     return 0;
    89 }
  • 相关阅读:
    文件名中含有空格读取时产生的异常
    R 常用清洗函数汇总
    Fluid 0.4 新版本正式发布:支持数据预热,优化小文件场景
    阿里云 Serverless 再升级,从体验上拉开差距
    Dubbo-go 源码笔记(二)客户端调用过程
    高质量的缺陷分析:让自己少写 bug
    微服务框架 Go-Micro 集成 Nacos 实战之服务注册与发现
    OpenYurt 深度解读:如何构建 Kubernetes 原生云边高效协同网络?
    在大规模 Kubernetes 集群上实现高 SLO 的方法
    双十一购物节,Nacos 1.4.0 + Go SDK 1.0.1发布
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/11626133.html
Copyright © 2011-2022 走看看