2 条题解

  • 0
    @ 2025-9-15 17:23:48

    贪心。把高度相同的连一块,然后看哪些需要新的机器。

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1005;
    int n,m,a[N][N],ans;
    struct node {
    	int x,y,h;
    } c[N*N];
    int tot;
    bool cmp(node A,node B) {
    	return abs(A.h)<abs(B.h);
    }
    int fa[N*N];
    bool hav[N*N];
    int Find(int x) {
    	if(x==fa[x])return x;
    	return fa[x]=Find(fa[x]);
    }
    void merge(int x,int y) {
    	x=Find(x),y=Find(y);
    	if(x!=y) {
    		fa[x]=y;
    		hav[y]|=hav[x];
    	}
    }
    int hax(int x,int y) {
    	return (x-1)*m+y;
    }
    int dx[]= {0,1,0,-1},dy[]= {1,0,-1,0};
    signed main() {
    	std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    	cin>>n>>m;
    	for(int i=1; i<=n; ++i) {
    		for(int j=1; j<=m; ++j) {
    			cin>>a[i][j];
    			fa[hax(i,j)]=hax(i,j);
    			c[++tot]= {i,j,a[i][j]};
    		}
    	}
    	sort(c+1,c+1+tot,cmp);
    	for(int i=1; i<=tot; ++i) {
    		int x=c[i].x,y=c[i].y;
    		for(int k=0; k<4; ++k) {
    			int xx=x+dx[k],yy=y+dy[k];
    			if(xx>=1&&yy>=1&&xx<=n&&yy<=m&&abs(a[xx][yy])<=abs(a[x][y])) {
    				merge(hax(x,y),hax(xx,yy));
    			}
    		}
    		if(abs(c[i].h)!=abs(c[i+1].h)) {
    			for(int j=i; j>=1; --j) {
    				if(abs(c[j].h)!=abs(c[i].h))break;
    				int xx=c[j].x,yy=c[j].y;
    				if(a[xx][yy]>0&&!hav[Find(hax(xx,yy))]){
    					hav[Find(hax(xx,yy))]=1,++ans;
    				}
    			}
    		}
    	}cout<<ans<<"\n";
    	return 0;
    }
    
    • 0
      @ 2025-9-13 17:48:43

      原题链接

      原题有一句话是:Of course, the communicating tubes principle makes its work, so draining one square results in lowering the water level or complete draining of those squares from which the water can flow down to the one with the pump

      感觉新题面完全没法体现这一点。

      理解到这句话后,题目是简单的。

      考虑贪心,从海拔最低的方格开始考虑。

      处理到每个方格时,将其与周围可以流水的方格连边。

      此时若这个连通块内存在一个抽水器,则这个方格的水会被处理。

      否则,若这个方格是一个农田,则需要在这里放一个抽水器。

      #include <bits/stdc++.h>
      using namespace std;
      
      static const int32_t dx[] = {0, 0, -1, 1};
      static const int32_t dy[] = {-1, 1, 0, 0};
      
      struct Dsu {
        vector<int8_t> tag;
        vector<size_t> fa;
      
        Dsu(size_t n) : tag(n, 0), fa(n) { iota(fa.begin(), fa.end(), 0); }
        void mark(size_t x) { tag[getf(x)] = true; }
        bool get_mark(size_t x) { return tag[getf(x)]; }
        size_t getf(size_t x) { return x == fa[x] ? x : fa[x] = getf(fa[x]); }
        void merge(size_t x, size_t y) {
          x = getf(x), y = getf(y);
          tag[y] |= tag[x], fa[x] = y;
        }
      };
      
      int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        size_t n, m;
        cin >> n >> m;
      
        vector<vector<bool>> farm(n, vector<bool>(m));
        vector<vector<int32_t>> height(n, vector<int32_t>(m));
        map<int32_t, vector<pair<size_t, size_t>>> query;
        for (size_t i = 0; i < n; ++i)
          for (size_t j = 0; j < m; ++j) {
            cin >> height[i][j];
            if (height[i][j] > 0)
              farm[i][j] = true;
            else
              height[i][j] = -height[i][j];
            query[height[i][j]].emplace_back(i, j);
          }
      
        size_t ans = 0;
        Dsu dsu(n * m);
        auto getid = [&](size_t i, size_t j) { return i * m + j; };
      
        for (const auto &v : query) {
          for (const auto &[i, j] : v.second) {
            for (size_t k = 0; k < 4; ++k) {
              size_t x = i + dx[k], y = j + dy[k];
              if (x < n && y < m && height[x][y] <= height[i][j])
                dsu.merge(getid(i, j), getid(x, y));
            }
          }
          for (const auto &[i, j] : v.second) {
            size_t u = getid(i, j);
            if (farm[i][j] && !dsu.get_mark(u)) {
              ++ans, dsu.mark(u);
            }
          }
        }
        cout << ans << '\n';
        return 0;
      }
      
      • 1

      信息

      ID
      395
      时间
      1000ms
      内存
      256MiB
      难度
      8
      标签
      (无)
      递交数
      25
      已通过
      4
      上传者