[算法学习记录] ABC402 A-D题解

A - CBC

遍历一下,看有多少个大写字母就行。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;

void solve()
{
	string S;cin >> S;
	
	for(int i = 0;i<S.size();i++) if(S[i]>='A'&&S[i]<='Z')cout << S[i];
}

int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int _ = 1;
	while(_--)solve();
	return 0;
}

B - Restaurant Queue

用栈就能解决,操作1就入栈,操作2就输出栈顶元素并出栈。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
queue<int> q;

void op1()
{
	int x;cin >> x;
	q.push(x);
}

void op2()
{
	int x = q.front();q.pop();
	cout << x <<"\n";
}

void solve()
{
	int q;cin >> q;
	while(q--)
	{
		int op;cin >> op;
		if(op==1)op1();
		else op2();
	}
}

int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int _ = 1;
	while(_--)solve();
	return 0;
}

C - Dislike Foods

本题数据量较大,如果我们用邻接表把每道菜的配料存在一起,暴力匹配肯定会超时;我们尝试反过来存每个配料存在于那几个菜中,接下来我们只要遍历每天适应的配料,就能轻松解决。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 3e5+5;
vector<int> g[N];
//存储每种配料存在于哪几道菜中
int b[N],flag[N];
//flag为每天适应的配料,flag,为每道菜的配料数量
bool vis[N];
//一道菜的每种配料都适应了,就标记为true

void solve()
{
	int n,m,count = 0;cin >> n >> m;
	
	for(int i = 1;i<=m;i++)
	{
		int k;cin >> k;
		flag[i] = k;
		while(k--)
		{
			int a;cin >> a;
			g[a].push_back(i);
		}
	}
	
	for(int i = 1;i<=n;i++)cin >> b[i];
	
	for(int i = 1;i<=n;i++)
	{
		for(auto &x : g[b[i]])
		{
			flag[x]--;
			if(!flag[x]&&!vis[x])
			{
				count++;
				vis[x] = true;
			}
		}
		
		cout << count <<"\n";
	}
	
}

int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int _ = 1;
	while(_--)solve();
	return 0;
}

D - Line Crossing

容易发现每天直线的每两个点的坐标之和只要相等(这里将它定义为斜率),这两条直线就平行。
我们可以先计算所有直线对的数量,在计算平行的直线对数量,总的减去平行的就是相交的。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll,ll>; 
const int N = 1e6+5,M = 3e5+5;
pii g[N]; 
ll k[N];
//存储斜率
map<ll,ll>mp;

void solve()
{
	ll n,m;cin >> n >> m;
	for(int i = 1;i<=m;i++)
	{
		ll a,b;cin >> a >> b;
		g[i] = {a,b};
	}
	
	for(int i = 1;i<=m;i++)
	{
		k[i] = (g[i].first + g[i].second) % n;
		if(mp.count(k[i]) == 0) mp[k[i]] = 1;
		else mp[k[i]]++;
	}
	//用map存储每种斜率的直线数量
	ll ans = m * (m - 1) / 2;
    //先计算总的
	for(auto &x : mp) ans -= 1ll * x.second * (x.second - 1) / 2;
	//计算相交的直线对数量(组合数C(n,2))
	cout << ans<<"\n";
}

int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int _ = 1;
	while(_--)solve();
	return 0;

posted @ 2025-04-23 20:27  林克还是克林  阅读(46)  评论(0)    收藏  举报