• [洛谷P5532] [CCO 2019] Sirtet


    前言

    可惜今天调试环境花太久时间,之后还在走廊无意义随机游走,所以三四题没时间了QAQ

    不然三四题至少出一道。

    题目

    洛谷

    讲解

    考虑直接求出每个块的下落距离。

    如果单独一个点一个点看,那么会造成影响的只会是一列当中的两个元素,设他们的坐标为 ((x_1,y),(x_2,y),x_1>x_2)

    设下落距离为 (dis),那么显然有 (dis_2+x_1-x_2-1ge dis_1),是一个差分约束的形式,然后我们把每个单点带回连通块,求出连通块两两之间的限制,直接跑差分约束即可。

    时间复杂度 (O(nmlog_2nm))

    据说还有模拟做法?

    代码

    赛后改动不大的代码
    //12252024832524
    #include <bits/stdc++.h>
    #define TT template<typename T>
    using namespace std;
    
    typedef long long LL;
    const int MAXN = 1000005;
    const int INF = 0x3f3f3f3f;
    int n,m;
    vector<char> G[MAXN];
    vector<int> a[MAXN],d[2][MAXN];
    int dx[4] = {1,-1},dy[4] = {0,0,1,-1};
    
    LL Read()
    {
    	LL x = 0,f = 1; char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    char gc()
    {
    	char c = getchar();
    	while(c != '.' && c != '#') c = getchar();
    	return c;
    }
    int f[MAXN];
    int findSet(int x){if(f[x]^x)f[x]=findSet(f[x]);return f[x];}
    void unionSet(int x,int y)
    {
    	x = findSet(x); y = findSet(y);
    	if(x^y) f[x] = y;
    }
    int bl[MAXN];
    int ID(int x,int y){return (x-1)*m+y;}
    int IDtot;
    struct node{int x,y;bool operator < (const node &px)const{return y > px.y;};};
    vector<node> g[MAXN];
    
    void solve1()
    {
    	int cnt = 0;
    	for(int i = 1;i <= n;++ i)
    		if(G[i][1] == '#') ++cnt;
    	for(int i = 1;i <= n;++ i,putchar('
    '))
    		if(i+cnt <= n) putchar('.');
    		else putchar('#');
    }
    
    int head[MAXN],tot;
    struct edge
    {
    	int v,w,nxt;
    }e[MAXN << 1];
    void Add_Edge(int x,int y,int z)
    {
    	e[++tot] = edge{y,z,head[x]};
    	head[x] = tot;
    }
    void Add_Double_Edge(int x,int y,int z)
    {
    	Add_Edge(x,y,z);
    	Add_Edge(y,x,z);
    }
    
    int dis[MAXN];
    void dij()
    {
    	for(int i = 1;i <= IDtot;++ i) dis[i] = INF;
    	priority_queue<node> q;
    	q.push(node{0,0});
    	while(!q.empty())
    	{
    		node t = q.top(); q.pop();
    		if(t.y > dis[t.x]) continue;
    		for(int i = head[t.x]; i ;i = e[i].nxt)
    			if(t.y+e[i].w < dis[e[i].v])
    				q.push(node{e[i].v,dis[e[i].v] = t.y+e[i].w}); 
    	}
    }
    
    int main()
    {
    //	freopen("tpt.in","r",stdin);
    //	freopen("tpt.out","w",stdout);
    	n = Read(); m = Read();
    	for(int i = n*m;i >= 1;-- i) f[i] = i;
    	for(int i = 1;i <= n;++ i)
    	{
    		G[i].resize(m+2);
    		d[0][i].resize(m+2);
    		d[1][i].resize(m+2);
    		for(int j = 1;j <= m;++ j) G[i][j] = gc();
    	}
    	if(m == 1){solve1();return 0;}
    	d[0][n+1].resize(m+2);
    	d[1][n+1].resize(m+2);
    	for(int i = 1;i <= n;++ i)
    		for(int j = 1;j <= m;++ j)
    		{
    			if(G[i][j] == '.') continue;
    			for(int k = 0;k < 4;++ k)
    			{
    				int tox = i+dx[k],toy = j+dy[k];
    				if(tox >= 1 && toy >= 1 && tox <= n && toy <= m && G[tox][toy] == '#')
    					unionSet(ID(i,j),ID(tox,toy));
    			}
    		}
    	for(int i = 1;i <= n;++ i)
    		for(int j = 1;j <= m;++ j)
    		{
    			if(G[i][j] == '.') continue;
    			int rt = findSet(ID(i,j));
    			if(!bl[rt]) bl[rt] = ++IDtot;
    			bl[ID(i,j)] = bl[rt];
    			g[bl[rt]].emplace_back(node{i,j});
    		}
    	for(int i = 1;i <= m;++ i) d[0][n+1][i] = n+1,d[1][n+1][i] = i;
    	for(int i = n;i >= 1;-- i)
    		for(int j = 1;j <= m;++ j)
    			if(i == n || G[i+1][j] == '#') d[0][i][j] = i+1,d[1][i][j] = j;
    			else d[0][i][j] = d[0][i+1][j],d[1][i][j] = d[1][i+1][j];
    	 for(int i = 1;i <= n;++ i)
    	 	for(int j = 1;j <= m;++ j)
    	 		if(G[i][j] == '#')
    	 		{
    	 			if(d[0][i][j] > n) Add_Edge(0,bl[ID(i,j)],d[0][i][j]-i-1);
    	 			else if(bl[ID(d[0][i][j],d[1][i][j])]^bl[ID(i,j)]) Add_Edge(bl[ID(d[0][i][j],d[1][i][j])],bl[ID(i,j)],d[0][i][j]-i-1);
    			}
    	dij();
    	for(int i = 1;i <= n;++ i)
    		for(int j = 1;j <= m;++ j)
    			G[i][j] = '.';
    	for(int i = 1;i <= IDtot;++ i)
    		for(auto A : g[i])
    			G[A.x+dis[i]][A.y] = '#';
    	for(int i = 1;i <= n;++ i,putchar('
    '))
    		for(int j = 1;j <= m;++ j)
    			putchar(G[i][j]);
    	return 0;
    }
    
  • 相关阅读:
    codevs1288 埃及分数
    [BZOJ1697][Usaco2007 Feb]Cow Sorting牛排序
    [BZOJ1628][Usaco2007 Demo]City skyline
    [Usaco2005 Mar]Out of Hay 干草危机
    [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居
    [BZOJ1691][Usaco2007 Dec]挑剔的美食家
    [BZOJ1668][Usaco2006 Oct]Cow Pie Treasures 馅饼里的财富
    [BZOJ1593][Usaco2008 Feb]Hotel 旅馆
    [BZOJ1637][Usaco2007 Mar]Balanced Lineup
    [BZOJ1650][Usaco2006 Dec]River Hopscotch 跳石子
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15411318.html
Copyright © 2020-2023  润新知