• [luogu5423]Valleys


    先考虑不要求有洞,那么可以将所有权值排序,然后不断插入,那么一个连通块就是一个答案,加上连通块大小即可
    考虑并查集如何判断是否有洞,可以发现对于任意一个无洞的直角多边形,都有$90度内角-90度外角=4$,而如果有洞显然就不是了(容易发现如果有k个洞,那么上述的值就应是$4-4k$)
    这个角度看上去很难维护,其实只需要考虑包含他的四个2*2的矩形即可(或者说这个新点的四个较上的角的变化),分类讨论:
    1.相邻的两个格子都没有,新增一个90度的内角
    2.相邻的两个格子恰有一个,减少一个90度的内角
    3.相邻的两个格子都有,且对角没有,减少两个90度的内角,新增一个90度的外角
    4.相邻的两个格子都有,且对角也有,减少一个90度的外角
    由此用并查集进行维护即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 1000005
     4 struct ji{
     5     int x,y,k;
     6 }a[N];
     7 int n,f[N],sz[N],sum[N],vis[1005][1005],dx[4]={-1,0,0,1},dy[4]={0,-1,1,0};
     8 long long ans;
     9 bool cmp(ji x,ji y){
    10     return x.k<y.k;
    11 }
    12 int id(int x,int y){
    13     return (x-1)*n+y;
    14 }
    15 int find(int k){
    16     if (k==f[k])return k;
    17     return f[k]=find(f[k]);
    18 }
    19 void add(int x,int y){
    20     sz[id(x,y)]=vis[x][y]=1;
    21     for(int i=0;i<4;i++){
    22         int tx=x+dx[i],ty=y+dy[i];
    23         if (vis[tx][ty]){
    24             if (find(id(tx,ty))==id(x,y))continue;
    25             sz[id(x,y)]+=sz[find(id(tx,ty))];
    26             sum[id(x,y)]+=sum[find(id(tx,ty))];
    27             f[find(id(tx,ty))]=id(x,y);
    28         }
    29     }
    30     for(int i=-1;i<2;i+=2)
    31         for(int j=-1;j<2;j+=2){
    32             int tx=x+i,ty=y+j,s=vis[tx][y]+vis[x][ty];
    33             if (!s)sum[id(x,y)]++;
    34             if (s==1)sum[id(x,y)]--;
    35             if (s==2){
    36                 if (vis[tx][ty])sum[id(x,y)]++;
    37                 else sum[id(x,y)]-=3;
    38             }
    39         }
    40     if (sum[id(x,y)]==4)ans+=sz[id(x,y)];
    41 }
    42 int main(){
    43     scanf("%d",&n);
    44     for(int i=1;i<=n;i++)
    45         for(int j=1;j<=n;j++){
    46             scanf("%d",&a[id(i,j)].k);
    47             a[id(i,j)].x=i;
    48             a[id(i,j)].y=j;
    49             f[id(i,j)]=id(i,j);
    50         }
    51     sort(a+1,a+n*n+1,cmp);
    52     for(int i=1;i<=n*n;i++)add(a[i].x,a[i].y);
    53     printf("%lld",ans);
    54 }
    View Code
  • 相关阅读:
    Building fresh packages卡很久
    后端阿里代码扫描
    npm 使用淘宝镜像
    git镜像
    mysql安装8.0.18
    idea2019.2.2版本破解
    JDK下载很慢
    解决GitHub下载速度慢下载失败的问题
    Hashtable多线程遍历问题
    2-18 求组合数 注:代码有问题找不出哪儿错了
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/12238555.html
Copyright © 2020-2023  润新知