Acwing周赛第一场BC

最大中位数

题目链接(https://www.acwing.com/problem/content/3581/)

**思路:**将所给数组进行排序,因为要找最大的中位数,所以操作所加的1一定加在中位数及以后的数字上面,二分一下答案即可。

代码:

#include 
using namespace std;
const int N = 2e5 + 10;
typedef long long LL;
LL a[N], b[N];
int n, m;

bool check (LL mid)
{
    //让 a[n / 2] == mid 其余的大于mid就可以
    LL sum = 0;
    for (int i = n / 2; i < n; i ++)
    {
        if (a[i] >= mid)
            break;
        sum += mid - a[i];
    }
    if (sum <= m) return true;
    else return false;
    
    
}
int main ()
{
	ios::sync_with_stdio (false);
	cin.tie (0); cout.tie (0);
	priority_queue <int, vector<int>, greater<int> > q;
	cin >> n >> m;
	LL r = 0;
	for (int i = 0; i <= n; i ++){
	     cin >> a[i];
	     r = max (r, a[i]);
	}
	sort (a, a + n);
	r += m;
	LL l = a[n / 2];
	while (l < r)
	{
	    LL mid = (l + r + 1) >> 1;
	    if (check (mid)) l = mid;
	    else r = mid - 1;
	}
	cout << l;
	
	return 0;
}

数字移动

题目链接(https://www.acwing.com/problem/content/3582/))

思路: 每个位置进行移动,最后都会回到自己的位置,因此会形成一个环,而因为有多个位置,所以会有多个独立的环(可以看成一组),所需要的操作次数这个位置所在环中的点数。

代码:

#include 
using namespace std;
const int N = 2e5 + 10;
int a[N], f[N], cnt[N];
int n, m;


int find (int x)
{
    if (x != f[x]) f[x] = find (f[x]);
    return f[x];
}
int main ()
{
	ios::sync_with_stdio (false);
	cin.tie (0); cout.tie (0);
	int t; cin >> t;
	while (t -- )
	{
		cin >> n;
		for (int i = 1; i <= n; i ++)
		{
		    f[i] = i; cnt[i] = 1;
		}
		
		    for (int i = 1; i <= n; i ++)
			{
			    cin >> a[i];
			    int fa = find (i), fb = find (a[i]);
			    if (fa != fb)
			    {
			        f[fa] = fb;
			        cnt[fb] += cnt[fa];
			    }
			
			}
		for (int i = 1; i <= n; i ++)
		    cout << cnt[find (i)] << " ";
		cout << "\n";
	}
	return 0;
}

你可能感兴趣的:(Acwing周赛,算法,c++)