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;
}