2020 China Collegiate Programming Contest Qinhuangdao Site

比赛链接

F. Friendly Group
题意,给你n个点,m条边,求从中选k个点,这k个点被z条线连起来,求最大的z-k。
首先如果加入一个点,那么这个值是不会变的,所以能加点就加点,然后每次边时如果这条变加不加都已经构成联通图了。那么就记录一下,最后求出所有(联通图的贡献-1)(因为并查集是构成圈时才开始加数)之和。

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define ull unsigned long long
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define endl "\n"
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 3e5 + 10;
const int maxm = 1e4 + 50;
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;
const ll  lnf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
int fa[maxn];
int find1(int a)
{
	return fa[a] == a ? a : fa[a]=find1(fa[a]);
}
set<int>st;
int num[maxn];
int main()
{
	int T;
	scanf("%d", &T);
	int cas = 0;
	while (T--)
	{
		int n,m;
		scanf("%d%d", &n,&m);
		for (int i = 0; i <= n; i++)
		{
			fa[i] = i;
			num[i] = 0;
		}
		int ans = 0;
		for (int i = 1; i <= m; i++)
		{
			int x, y;
			scanf("%d%d", &x, &y);
			int dx = find1(x);
			int dy = find1(y);
			if (dx == dy)
			{
				num[dx]++;
				continue;
			}
			fa[dx] = dy;
			num[dy] += num[dx];
		}
		st.clear();
		for (int i = 1; i <= n; i++)
		{
			st.insert(find1(i));
		}
		
		for (auto i : st)
		{
			ans += max(0, num[i] - 1);
		}
		printf("Case #%d: %d\n", ++cas,max(0, ans));
	}
	return  0;
}

E. Exam Results
题意:给定n个人每个人的考试分数有两种可能,及格分数为最高分数的p%,现在要求最多的及格人数。
这个题目放在一起排序想到了,但是不知道为什么当时想的是二分,虽然二分样例也过了,但是就是没过这个题目到现在还不明白为什么这个题目不能二分,然后训练赛后看题解才知道这是个双指针,我是真没想到。先放在一起连同位置信息一起排序,然后再用尾指针一直平移使得满足有n个人,再移动头指针选出符合条件的人。最后每移动一次尾指针更新一下答案。

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define ull unsigned long long
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define endl "\n"
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 3e5 + 10;
const int maxm = 1e4 + 50;
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;
const ll  lnf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
int n, p;
struct node
{
	int a, b;
};
vector<node>v;
int vis[maxn];
bool cmp(node A, node B)
{
	return A.a < B.a;
}
int main()
{
	int T;
	scanf("%d", &T);
	int cas = 0;
	while (T--)
	{
		v.clear();
		scanf("%d%d", &n, &p);
		for (int i = 1; i <= n; i++)
		{
			int x, y;
			scanf("%d%d", &x, &y);
			v.push_back({ x,i });
			v.push_back({ y,i });
			vis[i] = 0;
		}
		vis[0] = 0;
		sort(v.begin(), v.end(), cmp);
		int tail = -1, now=0;
		int ans = 0;
		while (now != n)
		{
			if (!vis[v[++tail].b])now++;
			vis[v[tail].b]++;
		}
		now--;
		vis[v[tail].b]--;
		tail--;
		int head = 0;
		while (tail < 2 * n - 1)
		{
		
			tail++;
			//cout << tail << endl;
			vis[v[tail].b]++;
			if (vis[v[tail].b] == 1)now++;
			while (head < tail && (ll)v[head].a * 100 < (ll)v[tail].a * p)
			{
				vis[v[head].b]--;
				if (!vis[v[head].b])now--;
				head++;
			}
			ans = max(ans, now);
		}
		printf("Case #%d: %d\n", ++cas, ans);
	}
	return  0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值