• Atcoder Grand Contest 004 题解


    A - Divide a Cuboid

    如果一边是偶数,肯定一刀切一半最优,否则看一下切出来的差就是另外两边的乘积。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    int A, B, C; 
     
    int main()
    {
    	giii(A, B, C);
    	if (A % 2 == 0 || B % 2 == 0 || C % 2 == 0) puts("0");
    	else printf("%lld
    ", min(1LL * A * B, min(1LL * B * C, 1LL * A * C)));
    	return 0;
    }
    

      

    B - Colorful Slimes

    枚举转了y次,那么一个点被造出来的花费就是min(a[i-y]...a[i]),最后加上x*y对所有情况取min就好了。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    int n, a[2010], x, mn[2010][2010];
     
    long long ans;
     
    int main()
    {
    	gii(n, x);
    	for (int i = 1; i <= n; ++i) gi(a[i]), ans += a[i];
    	for (int i = 1; i <= n; ++i)
    	{
    		mn[i][i] = a[i];
    		for (int j = i + 1; j <= n; ++j)
    			mn[i][j] = min(mn[i][j - 1], a[j]);
    	}
    	for (int i = 0; i <= n; ++i)
    	{
    		long long ret = 1LL * x * i;
    		for (int j = 1; j <= n; ++j)
    		{
    			int k = j - i;
    			if (k < 1) k += n, ret += min(mn[k][n], mn[1][j]);
    			else ret += mn[k][j];
    		}
    		ans = min(ans, ret);
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    

      

    C - AND Grid

    两边摆成类似正反E字交错放,重复地方两个都放就好了。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    int n, m;
     
    char str[510][510];
     
    int main()
    {
    	gii(n, m);
    	for (int i = 1; i <= n; ++i) scanf("%s", str[i] + 1);
    	for (int i = 1; i <= n; ++i)
    	{
    		for (int j = 1; j <= m; ++j)
    		{
    			if (((j == 1 || (i & 1)) && j != m) || str[i][j] == '#')
    				putchar('#');
    			else
    				putchar('.');
    		}
    		putchar('
    ');
    	}
    	for (int i = 1; i <= n; ++i)
    	{
    		for (int j = 1; j <= m; ++j)
    		{
    			if (((j == m || !(i & 1)) && j != 1) || str[i][j] == '#')
    				putchar('#');
    			else
    				putchar('.');
    		}
    		putchar('
    ');
    	}
    }
    

      

    D - Teleporter

    首先,1号必须连自己,因为如果1有在一个环上,环上每个点走k次结果都不一样,其它也只能改为1号最优。

    那么,省下就是一棵树了,bfs一遍即可。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    const int N = 1e5 + 10;
     
    int n, k, a[N]; 
     
    int ans = 0;
     
    int deg[N], dep[N];
     
    int main()
    {
    	gii(n, k); --k;
    	for (int i = 1; i <= n; ++i) gi(a[i]);
    	if (a[1] != 1) ++ans, a[1] = 1;
    	for (int i = 1; i <= n; ++i)
    		++deg[a[i]];
    	static int q[N]; int l = 0, r = 0;
    	for (int i = 1; i <= n; ++i)
    	{
    		if (!deg[i]) q[r++] = i;
    	}
    	while (l < r)
    	{
    		int u = q[l++];
    		--deg[a[u]];
    		if (!deg[a[u]]) q[r++] = a[u];
    		if (dep[u] == k && a[u] != 1) a[u] = 1, ++ans;
    		else dep[a[u]] = max(dep[a[u]], dep[u] + 1);
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

    E - Salvage Robots

    能走的区域是一个矩形,但是能取到的就长得奇形怪状了,所以我们就写一个四位dp,算算边界就好了。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    int H, W;
     
    char str[110][110];
     
    int cnt[110][110];
     
    int sum(int x1, int y1, int x2, int y2)
    {
    	x1 = max(x1, 1), x1 = min(x1, H);
    	x2 = max(x2, 1), x2 = min(x2, H);
    	y1 = max(y1, 1), y1 = min(y1, W);
    	y2 = max(y2, 1), y2 = min(y2, W);
    	if (x1 > x2) return 0;
    	if (y1 > y2) return 0;
    	//cerr << x1 << ", " << y1 << " and " << x2 << ", " << y2 << endl;
    	return cnt[x2][y2] + cnt[x1 - 1][y1 - 1] - cnt[x1 - 1][y2] - cnt[x2][y1 - 1];
    }
     
    int f[2][110][110][110];
     
    int main()
    {
    	gii(H, W);
    	for (int i = 1; i <= H; ++i)
    		scanf("%s", str[i] + 1);
    	int x = 0, y = 0;
    	for (int i = 1; i <= H; ++i)
    		for (int j = 1; j <= W; ++j)
    			if (cnt[i][j] = (str[i][j] == 'o'), str[i][j] == 'E')
    				x = i, y = j;
    	for (int i = 1; i <= H; ++i)
    		for (int j = 1; j <= W; ++j)
    			cnt[i][j] += cnt[i - 1][j] + cnt[i][j - 1] - cnt[i - 1][j - 1];
    	int ans = 0;
    	for (int l = 0; x + l <= H; ++l)
    		for (int r = 0; x - r > 0; ++r)
    			for (int u = 0; y + u <= W; ++u)
    				for (int d = 0; y - d > 0; ++d)
    				{
    					int L = l & 1;
    					f[L][r][u][d] = 0;
    					int left = x - r, right = x + l;
    					int up = y - d, down = y + u;
    					left = max(1 + l, left);
    					right = min(H - r, right);
    					up = max(up, 1 + u);
    					down = min(down, W - d);
    					if (l && l + r + x <= H) f[L][r][u][d] = max(f[L][r][u][d], f[L ^ 1][r][u][d] + sum(x + l, up, x + l, down));
    					if (r && l + r <= x - 1) f[L][r][u][d] = max(f[L][r][u][d], f[L][r - 1][u][d] + sum(x - r, up, x - r, down));
    					if (u && u + d + y <= W) f[L][r][u][d] = max(f[L][r][u][d], f[L][r][u - 1][d] + sum(left, y + u, right, y + u));
    					if (d && u + d <= y - 1) f[L][r][u][d] = max(f[L][r][u][d], f[L][r][u][d - 1] + sum(left, y - d, right, y - d));
    					//cerr << l << ", " << r << ", " << u << ", " << d << " : " << f[l][r][u][d] << endl; 
    					ans = max(ans, f[L][r][u][d]);
    				}
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

    F - Namori

    我们首先可以发现一个性质,黑色只能成对出现而且,这两个点距离为奇数,次数是距离。

    那么树就很好写了,只要一个启发式合并,求深度的奇偶性。

    环套树我们把它缩成环,然后每个附上权值d[i],偶环就是一个负载平衡问题,奇环我们可以断开一条边,因为那条边的作用是改变奇偶用的,所以我们扫一遍就能知道会改变多少次。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    const int N = 1e5 + 10;
     
    VI edge[N];
     
    int n, m;
     
    namespace task1
    {
    	set<int> e[N][2];
    	
    	int fa[N], dep[N], check_cnt;
    	
    	void dfs1(int u)
    	{
    		dep[u] = dep[fa[u]] + 1;
    		e[u][dep[u] & 1].insert(u);
    		if (dep[u] & 1) ++check_cnt;
    		else --check_cnt;
    		for (auto v : edge[u])
    		{
    			if (v == fa[u]) continue;
    			fa[v] = u;
    			dfs1(v);
    		}
    	}
    	
    	long long ans;
    	
    	void dfs2(int u)
    	{
    		for (auto v : edge[u])
    		{
    			if (v == fa[u]) continue;
    			dfs2(v);
    			if (e[u][1].size() < e[v][1].size())
    				e[u][1].swap(e[v][1]);
    			for (auto x : e[v][1])
    				e[u][1].insert(x);
    			if (e[u][0].size() < e[v][0].size())
    				e[u][0].swap(e[v][0]);
    			for (auto x : e[v][0])
    				e[u][0].insert(x);
    		}
    		if (e[u][1].size() && e[u][0].size())
    		{
    			int s = min(e[u][1].size(), e[u][0].size());
    			set<int>::iterator it1 = e[u][1].begin(), it2 = e[u][0].begin();
    			static PII stk[N]; int tp = 0;
    			for (int i = 1; i <= s; ++i)
    			{
    				int v1 = *it1;
    				int v2 = *it2;
    				stk[++tp] = mp(v1, v2);
    				ans += dep[v1] + dep[v2] - (dep[u] << 1);
    				//cerr << v1 << ", " << v2 << ", " << u << endl;
    				++it1, ++it2;
    			}
    			for (int i = 1; i <= tp; ++i)
    				e[u][1].erase(stk[i].fi), e[u][0].erase(stk[i].se);
    		}
    	}
    	
    	void solve()
    	{
    		dfs1(1);
    		if (check_cnt)
    		{
    			puts("-1");
    			return;
    		}
    		dfs2(1);
    		printf("%lld
    ", ans);
    	}
    }
     
    namespace task2
    {
    	bool vis[N], cir[N];
    	int use_fa[N];
    	vector<int> circle;
    	bool exit_flag;
    	void dfs1(int u)
    	{
    		vis[u] = 1;
    		for (auto v : edge[u])
    		{
    			if (exit_flag) return;
    			if (use_fa[u] == v) continue;
    			if (vis[v])
    			{
    				while (u != v) circle.pb(u), cir[u] = 1, u = use_fa[u];
    				circle.pb(v), cir[v] = 1;
    				exit_flag = 1;
    				return;
    			}
    			use_fa[v] = u;
    			dfs1(v);
    		}
    	}
    	
    	int dep[N], fa[N];
    	
    	set<int> e[N][2];
    	
    	void dfs2(int u)
    	{
    		dep[u] = dep[fa[u]] + 1;
    		e[u][dep[u] & 1].insert(u);
    		for (auto v : edge[u])
    		{
    			if (v == fa[u]) continue;
    			if (cir[v]) continue;
    			fa[v] = u;
    			dfs2(v);
    		}
    	}
    	
    	long long ans;
    	
    	void dfs3(int u)
    	{
    		for (auto v : edge[u])
    		{
    			if (v == fa[u]) continue;
    			if (cir[v]) continue;
    			dfs3(v);
    			if (e[u][1].size() < e[v][1].size())
    				e[u][1].swap(e[v][1]);
    			for (auto x : e[v][1])
    				e[u][1].insert(x);
    			if (e[u][0].size() < e[v][0].size())
    				e[u][0].swap(e[v][0]);
    			for (auto x : e[v][0])
    				e[u][0].insert(x);
    		}
    		if (e[u][1].size() && e[u][0].size())
    		{
    			int s = min(e[u][1].size(), e[u][0].size());
    			set<int>::iterator it1 = e[u][1].begin(), it2 = e[u][0].begin();
    			static PII stk[N]; int tp = 0;
    			for (int i = 1; i <= s; ++i)
    			{
    				int v1 = *it1;
    				int v2 = *it2;
    				stk[++tp] = mp(v1, v2);
    				ans += dep[v1] + dep[v2] - (dep[u] << 1);
    				//cerr << v1 << ", " << v2 << ", " << u << endl;
    				++it1, ++it2;
    			}
    			for (int i = 1; i <= tp; ++i)
    				e[u][1].erase(stk[i].fi), e[u][0].erase(stk[i].se);
    		}
    	}
    	
    	int d[N];
    	
    	void solve()
    	{
    		dfs1(1);
    		for (auto root : circle)
    		{
    			//cerr << root << endl;
    			dfs2(root), dfs3(root);
    			if (e[root][1].size())
    			{
    				for (auto v : e[root][1])
    					++d[root], ans += dep[v] - 1;
    			}
    			else if (e[root][0].size())
    			{
    				for (auto v : e[root][0])
    					--d[root], ans += dep[v] - 1;
    			}
    		}
    		int vtx = SZ(circle);
    		//cerr << "ok!" << endl;
    		if (vtx % 2 == 0)
    		{
    			int sum = 0;
    			for (int i = 0; i < vtx; ++i)
    			{
    				if (i & 1) d[circle[i]] = -d[circle[i]];
    				sum += d[circle[i]];
    			}
    			if (sum) 
    			{
    				puts("-1");
    				return;
    			}
    			static vector<int> t;
    			t.pb(-d[circle[0]]);
    			for (int i = 1; i < vtx; ++i)
    			{
    				d[circle[i]] += d[circle[i - 1]];
    				t.pb(-d[circle[i]]);
    			}
    			sort(t.begin(), t.end());
    			int v = t[SZ(t) >> 1];
    			for (auto x : t)
    				ans += abs(x - v);
    			printf("%lld
    ", ans);
    		}
    		else
    		{
    			int sum = 0;
    			for (int i = 0; i < vtx; ++i)
    			{
    				if (i & 1) d[circle[i]] = -d[circle[i]];
    				sum += d[circle[i]];
    			}
    			if (sum % 2 != 0)
    			{
    				puts("-1");
    				return;
    			}
    			ans += abs(sum / 2);
    			d[circle[0]] -= sum / 2;
    			d[circle[vtx - 1]] += sum / 2;
    			for (int i = 0; i < vtx - 1; ++i)
    			{
    				ans += abs(d[circle[i]]);
    				d[circle[i + 1]] += d[circle[i]];
    			}
    			printf("%lld
    ", ans);
    		} 
    	}
    }
     
    int main()
    {
    	gii(n, m);
    	for (int i = 1; i <= m; ++i)
    	{
    		int u, v;
    		gii(u, v);
    		edge[u].push_back(v);
    		edge[v].push_back(u);
    	}
    	if (m == n - 1)
    	{
    		task1::solve();
    		return 0;
    	}
    	task2::solve();
    	return 0;
    }
    

      

    1. //waz
    2. #include<bits/stdc++.h>
    3.  
    4. usingnamespace std;
    5.  
    6. #define mp make_pair
    7. #define pb push_back
    8. #definefi first
    9. #define se second
    10. #define ALL(x)(x).begin(),(x).end()
    11. #define SZ(x)((int)((x).size()))
    12.  
    13. typedef pair<int,int> PII;
    14. typedef vector<int> VI;
    15. typedeflonglong int64;
    16. typedefunsignedintuint;
    17. typedefunsignedlonglong uint64;
    18.  
    19. #define gi(x)((x)= F())
    20. #define gii(x, y)(gi(x), gi(y))
    21. #define giii(x, y, z)(gii(x, y), gi(z))
    22.  
    23. int F()
    24. {
    25. char ch;
    26. int x, a;
    27. while(ch = getchar(),(ch <'0'|| ch >'9')&& ch !='-');
    28. if(ch =='-') ch = getchar(), a =-1;
    29. else a =1;
    30. x = ch -'0';
    31. while(ch = getchar(), ch >='0'&& ch <='9')
    32. x =(x <<1)+(x <<3)+ ch -'0';
    33. return a * x;
    34. }
    35.  
    36. constint N =1e5+10;
    37.  
    38. int n, k, a[N];
    39.  
    40. int ans =0;
    41.  
    42. int deg[N], dep[N];
    43.  
    44. int main()
    45. {
    46. gii(n, k);--k;
    47. for(int i =1; i <= n;++i) gi(a[i]);
    48. if(a[1]!=1)++ans, a[1]=1;
    49. for(int i =1; i <= n;++i)
    50. ++deg[a[i]];
    51. staticint q[N];int l =0, r =0;
    52. for(int i =1; i <= n;++i)
    53. {
    54. if(!deg[i]) q[r++]= i;
    55. }
    56. while(l < r)
    57. {
    58. int u = q[l++];
    59. --deg[a[u]];
    60. if(!deg[a[u]]) q[r++]= a[u];
    61. if(dep[u]== k && a[u]!=1) a[u]=1,++ans;
    62. else dep[a[u]]= max(dep[a[u]], dep[u]+1);
    63. }
    64. printf("%d ", ans);
    65. return0;
    66. }
  • 相关阅读:
    Python第一周作业
    turtle库的学习笔记
    绘制五角星
    绘制六角形
    绘制同心圆
    绘制叠加三角形
    Slash And Black Slash/正斜杠和反斜杠
    OpenCv中avi视频的读取问题,以及内部格式要求
    OpenCv和matlab对图像的读取
    个人项目进度
  • 原文地址:https://www.cnblogs.com/AnzheWang/p/9615564.html
Copyright © 2020-2023  润新知