2024-05-06-ABC352

ABC352讲解

A - AtCoder Line

题意:铁路上有N个车站,编号为1,2,3,...,N,有趟列车从1号车站,依次停靠2,3,...,N号站,有另一趟列车从N号车站反过来行驶。现在高桥要从X站前往Y站,问他坐的车是否会在Z站停车。

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, x, y, z;
    cin >> n >> x >> y >> z;
 
    if (x > y) {
      swap(x, y);
    }
    
    if (x <= z and z <= y) {
      cout << "Yes\n";
    } else {
        cout << "No\n";
    }
    return 0;
}

B - Typing

题意:给定正确的字符串和实际输入的字符串,输出实际输入的字符串中正确输入的字符的下标。

#include <bits/stdc++.h>
using namespace std;
int main() {
    string s, t;
    cin >> s >> t;
 
    for (int i = 0, j = 0; j < t.size(); j++) {
      if (s[i] == t[j]) {
        cout << j + 1 << ' ';
          i++;
      }
    }
 
    return 0;
}

C - Standing On The Shoulders

题意:给定 n 个巨人从肩膀到地面的高度和从头到地面的高度,将 n 个巨人堆成一个“柱子”,处于高处的巨人站在身下的巨人的肩膀上。依次放完,问最后放置的巨人的头离地最高能够有多高。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
	int n;
	cin >> n;
	vector a(n, 0), b(n, 0);
	int mx = 0;
	ll sum = 0;
	for (int i = 0; i < n; i++) {
		cin >> a[i] >> b[i];
		sum += a[i];
		mx = max(mx, b[i] - a[i]);
	}

	cout << sum + mx;

	return 0;
}

D - Permutation Subsequence

题意:从给定的大小为 n 的排列 p 中抽出 k 个来,这 k 个元素经过排序后需要是公差为 1 的等差数列,最小化这 k 个数中的最大下标和最小下标的差,输出这个最小值。

解法:滑动窗口枚举k个元素的区间。

#include <bits/stdc++.h>
 
using namespace std;
using ll = long long;
 
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
 
  int n, k;
  cin >> n >> k;
 
  vector a(n, 0);
  for (int i = 0; i < n; i++) {
    int x;
    cin >> x;
    x--;
    a[x] = i;
  }
 
  int ans = INT_MAX;
  set<int> st;
  for (int i = 0; i < n; i++) {
    st.insert(a[i]);
    if (i >= k - 1) {
      ans = min(ans, *st.rbegin() - *st.begin());
      st.erase(a[i - k + 1]);
    }
  }
  cout << ans;
 
  return 0;
}

E - Clique Connect

题意:给定 n 个点的带权无向图,和 m 次操作,每次操作给定点数 k 和边权 c,然后将给定的 k 个点两两加边,边权为 c 。最后求最小生成树的边权。

解法:一个裸的kruscal最小生成树。

#include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)n;i++)
#define ll long long
#define fi first
#define se second
#define pb push_back
using namespace std;
int n,m;
ll ans,cnt;
pair<ll,vector<int> > v[200005];
int fa[200005];
int findfa(int x)
{
	if(fa[x]==x) return x;
	else return fa[x]=findfa(fa[x]);
}
int main()
{
	cin>>n>>m;
	rep(i,m)
	{
		int k;
		cin>>k>>v[i].fi;
		rep(j,k)
		{
			int x;
			cin>>x;
			v[i].se.pb(x);
		}
	}
	rep(i,n) fa[i+1]=i+1;
	sort(v,v+m);
	rep(i,m)
	{
		rep(j,v[i].se.size())
		{
			if(!j) continue;
			int fx=findfa(v[i].se[j]),fy=findfa(v[i].se[j-1]);
			if(fx!=fy)
			{
				ans+=v[i].fi;
				fa[fx]=fy;
				cnt++;
			}
		}
	}
	if(cnt!=n-1) cout<<-1;
	else cout<<ans;
	return 0;
}

F - Estimate Order

题意:有 n 个人的具体排名未知。已知这 n 个人的排名各不相同,以及 m 个条件,每个条件是 a 和 b 的排名差。需要通过已知信息求出可以确定排名的人的排名。

解法:首先处理出所有的连通块,对于每一个连通块,连通块中一个的位置确定了,其他的位置都确定了。我们在给每一个连通块做一个mask,表示他们需要占领的位置,比如mask是10011,表示连通块内有三个元素,他们可以是1、4、5名,也可以是2、5、6名等等,要注意处理mask的时候要存储好这个mask内每一个1的实际的人的下标。然后就是暴力dfs每一个连通块,把每一个块的mask往一开始为空的总mask里塞,对于每一个连通块,记录他们在有几种不同位置的合法方案,如果最后一个连通块的合法方案数唯一,那么这个连通块内的所有人的排名都是唯一的。

需要注意的是,如果把大小为1的连通块也放进去,那么整体时间复杂度会退化到O(n!),不放的话,时间复杂度就是O((n/2)!),是可以通过的,就是最后需要特别处理一下大小为1的块,即不受任何约束的人。

#include<bits/stdc++.h>
#define rep(i,n) for(int i=1;i<=(int)n;i++)
#define For(i,n) for(int i=0;i<(int)n;i++)
#define ll long long
#define fi first
#define se second
#define pb push_back
#define pii pair<int,int>
using namespace std;
vector<pair<int, int> > v[20];
int n, m, single, nsingle;
bool vis[20];
int sum[20];
vector<pii > p[20];
vector<pii > masks;
int pos[20], ans[20];
set<int> lmask;
bool flag = 0;

void dfs(int x, int dep, int id) {
	vis[x] = 1;
	p[id].pb({dep, x});
	for (auto y : v[x]) {
		if (!vis[y.fi]) {
			dfs(y.fi, dep + y.se, id);
		}
	}
}
int dfs2(int x, int mask) {
	if (x == (int)masks.size()) {
		lmask.insert(mask);
		return 1;
	}
	int tmp = masks[x].fi, f = 0;
	rep(i, n) {
		if ((tmp << i) >= (1 << (n + 1))) break;
		if ((tmp << i)&mask) continue;
		int t = dfs2(x + 1, mask | (tmp << i));
		if (t) {
			f = 1;
			if (sum[x] == 0) {
				pos[x] = i;
				sum[x]++;
			} else {
				if (pos[x] != i) sum[x]++;
			}
		}
	}
	return f;
}
int main() {
	cin >> n >> m;
	rep(i, m) {
		int x, y, c;
		cin >> x >> y >> c;
		v[x].pb({y, -c});
		v[y].pb({x, c});
	}
	int k = 0;
	rep(i, n) {
		if (!vis[i]) {
			dfs(i, 0, ++k);
			if (p[k].size() >= 2) {
				sort(p[k].begin(), p[k].end());
				int pls = -p[k][0].fi, mask = 0;
				for (auto it : p[k]) mask = mask | (1 << (it.fi + pls));
				masks.pb({mask, k});
			} else {
				single++;
				nsingle = i;
			}
		}
	}
	dfs2(0, 0);

	For(i, masks.size()) {
		if (sum[i] == 1) {
			int tmp = masks[i].fi << pos[i], k = 0;
			rep(j, n) {
				if (tmp & (1 << j)) {
					ans[p[masks[i].se][k++].se] = j;
				}
			}
		}
	}
	if (single == 1 && lmask.size() == 1) {
		int tmp = *lmask.begin();
		rep(i, n) if (!((1 << i)&tmp)) {
			ans[nsingle] = i;
			break;
		}
	}
	rep(i, n) {
		if (!ans[i]) cout << "-1 ";
		else cout << ans[i] << " ";
	}
	return 0;
}
posted @ 2024-11-30 23:27  ~清渠~  阅读(1)  评论(0编辑  收藏  举报