本题目的意思是给定一个n*m的数阵(n,m<=1000),并给定T个递增的权值序列,对每一个要求输出大于该值的所有格子组成的四连块个数。
思路:
给所有格子按权排序,从大到小处理这T个数,每次只需把满足条件的格子加入并查集,并在合并过程中动态统计联通分量的个数。
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <set> #include <map> #include <string> #include <list> #include <cstdlib> #include <queue> #include <stack> #include <cmath> #include <bitset> #include <cassert> #define ALL(a) a.begin(), a.end() #define clr(a, x) memset(a, x, sizeof a) #define X first #define Y second #define pb push_back #define lowbit(x) (x&(-x)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rep1(i,x,y) for(int i=x;i<=y;i++) #define rep(i,n) for(int i=0;i<(int)n;i++) using namespace std; const double eps = 1e-10; typedef long long LL; typedef long long ll; typedef pair<int, int> pii; const int oo =0x3f3f3f3f; const int N = 1e6+100; typedef pair<int,pii> pip; pip a[N]; int n,m , b[N] ,all = 0,pa[N] ,ans[N]; int find(int x){ if(x == -1) return -1; return (pa[x]==x ? x:pa[x]=find(pa[x])); } const int dx[]={-1,0,1,0}; const int dy[]={0,1,0,-1}; void add(pii u){ int pre = u.X*m+u.Y; pa[pre] = pre; all++; rep(d,4){ int nx = u.first+dx[d], ny = u.second+dy[d]; if(nx>=0&&nx<n&&ny>=0&&ny<m){ int p = nx*m+ny , px = find(p); if(px==-1) continue; int ppre = find(pre); if(ppre != px){ all--; pa[ppre] = px; } } } } int main() { int T; scanf("%d",&T); while(T--){ scanf("%d %d",&n,&m); int x , q ,cnt = 0; rep1(i,0,n-1) rep1(j,0,m-1) scanf("%d",&x),a[cnt++]=pip(x,pii(i,j)); sort(a,a+cnt); rep(i,cnt) pa[i] = -1; scanf("%d",&q); rep1(i,1,q) scanf("%d",&b[i]); int p = cnt-1; all = 0; for(int i=q;i>=1;i--){ while(p>=0 && a[p].first > b[i]) add(a[p--].second); ans[i] = all; } rep1(i,1,q){ printf("%d ",ans[i]); } printf("\n"); } return 0; }