Islands UVA - 1665

题意:输入一个n * m 矩阵,每个格子里都有1个[1,1e9]的正整数。再输入T个整数ti(0<=t1<=t2<=...<=tT<=1e9),对于每个ti,输出大于ti的正整数组成多少个四连块。

思路:1.并查集计算有多少连通块

2.因为T个整数是按大小顺序已经排好的,所以可以倒着来在算完ti的基础上计算t(i - 1),每个格子记为一个点,将格子按照格子内的值从小到大排列,从最后一个格子开始判断是否大于ti,然后查看四周是否可以合并。当所有的格子都枚举完时,若ti还没计算完,这时所有没算完的ti都继承已经计算完成的最后一个ti的答案,因为此时大的格子的连通块数一定也是小格子的答案。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int maxn = 1000 + 2;
int a[maxn][maxn];
int fa[maxn * maxn];
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};
int n,m,T,ans[100000+ 2];
struct node
{
    int x,y,val;
    bool operator < (const node & q)const
    {
        return val < q.val;
    }
} poi[maxn*maxn];
int found(int p)
{
    if(fa[p] == p) return p;
    return fa[p] = found(fa[p]);
}
int main()
{
    int N; scanf("%d",&N);
    while(N--)
    {
        scanf("%d%d",&n,&m);
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                scanf("%d",&a[i][j]);
                poi[i * m + j].x = i;
                poi[i * m + j].y = j;
                poi[i * m + j].val = a[i][j];
            }
        }
        sort(poi,poi + n * m);
        memset(fa,-1,sizeof(fa));
        int sum = 0; scanf("%d",&T);
        for(int i = 0; i < T; i++) scanf("%d",&ans[i]);
        int k = n * m - 1;
        for(int i = T - 1; i >= 0; i--) //要求的
        {
            while(k >= 0 && ans[i] < poi[k].val)
            {
                int pos = poi[k].x * m + poi[k].y;
                if(fa[pos] == -1) fa[pos] = pos,sum++;
                for(int j = 0; j < 4; j++)
                {
                    int nx = poi[k].x + dx[j];
                    int ny = poi[k].y + dy[j];
                    if(nx >= 0 && nx < n && ny >= 0 && ny < m && a[nx][ny] > ans[i])
                    {
                        int ppos = nx * m + ny;
                        if(fa[ppos] != -1)
                        {
                            int u = found(fa[pos]);
                            int v = found(fa[ppos]);
                            if(u != v) fa[v] = u,sum--;
                        }
                    }
                }
                k--;
            }
            if(k < 0)
            {
                for(; i >= 0; i--) ans[i] = sum;
                break;
            }
            ans[i] = sum;
        }
        for(int i = 0; i < T; i++) printf("%d ",ans[i]);
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sgsyacm/article/details/87928218