【周赛2】《产生冠军》《Graveyard Design》《Number of Pairs》

 C

题目来源

Problem - 2094

解释

  • 判断冠军产生的标准即判断一场都没有输的人是否唯一
  • 使用STL-map,第一个值放的是sting类 即姓名 第二个值存放他们的输赢状况
  • 输入a和b,如果当前姓名没有被输入过,则输入一个姓名并将输赢状况先置为1
  • 使用一个map类的迭代器,注意到mp.end()指向的是最后一个元素后一个的地址
  • 迭代器需要使用this指针来指向第二个值
  • 记录cnt的情况,如果第二个值为1的人数严格大于1 则不能判断输赢

关于map的STL使用参考:

C++ STL详解(3)_ACfun-CSDN博客

代码段

int main()
{

    nathan;
    int n;
    while (cin >> n && n != 0)
    {
        map<string, bool> mps;
        string a, b;
        while (n--) 
        {
            cin >> a >> b;
            if (mps.count(a)==0) mps[a] =1;
            if (mps.count(b)==0) mps[b] =1;
            mps[b] =0;
        }
        map<string, bool>::iterator it;
        int cnt = 0;
        for (it = mps.begin(); it != mps.end(); it++)
            if (it->second ==1) cnt++;
        cout << (cnt == 1 ? "Yes" : "No") << endl;
    }   
       
}

E

题目来源

2100 -- Graveyard Design

简述

  • 给定一个数n
  • 要求一个递增的数列,a1,a2,a3满足所有数的平方和等于n
  • 首先输出一共有k个这样的数列,再输出k行数列的具体内容

解释

  • 本题是典型的尺取法思想
  • 首先先将右端点r推向最远方,直到满足1-r的平方和等于n
  • 注意到如果一直推到r*r>n依旧没有符合的情况,则表示没有这样的数列
  • 这个也作为退出while(1)循环的唯一出口
  • 当sum=n时,我们将区间长度与包括左端点l和右端点r-1的数对pair同时存入ans数组中
  • 然后再将左端点l向右推进
  • 这时再进入第一个while循环推动右端点r直到再次满足sum=n,再次记录新的答案ans

代码段

int main()
{
	ll n;
	cin >> n;
	ll l = 1, r = 1, sum = 0, cnt = 0;
	pii ans[10000];
	while (1)
	{
		while (sum+r*r <=n)
		{
			sum += r * r;
			r++;
		}
		if (sum == n)
		{
			ans[cnt++] =
				pii(r - l, pair<ll, ll>(l, r - 1));
		}
		sum -= l * l;
		l++;
		if (r * r > n)break;
	}
	cout << cnt<< endl;
	for (int i = 0; i < cnt; i++)
	{
		cout << ans[i].first << ' ';
		for (ll j = ans[i].second.first; j<= ans[i].second.second; j++)
			cout << j << ' ';
		cout << endl;
	}
}

F

题目来源

Problem - 1538C - Codeforces

简述

  • 在数组中寻找ai和aj,给定l与r
  • 要求 l<=ai+aj<=r

解释

  • 这道题可以用二分法来手写处理,当然也可以使用STL
  • 先将数组排序好
  • 指针i遍历数组a[i]
  • 对于每一个a[i]我们使用STL-upper_bound和lower_bound
  • 查找仅在a[i]之前的a[j]是否有满足条件的元素
  • upper_bound:指向第一个严格大于r-a[j]的元素地址
  • lower_bound:指向第一个大于等于l-a[i]的元素地址
  • 所以区间长度即为upper_bound-lower_bound

代码段

void solve()
{
	int n, l, r;
	cin >> n >> l >> r;
	vector<int>a(n);
	for (auto& x : a)cin >> x;
	ll cnt = 0;
	sort(a.begin(), a.end());
	for (int i = 0; i < n; i++)
	{
		cnt+=
		upper_bound(a.begin(), a.begin()+i, r - a[i])- lower_bound(a.begin(), a.begin()+i, l - a[i]);
	}
	cout << cnt << endl;
}
int main()
{
	int t;
	cin >> t;
	while (t--)
		solve();
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nathan Qian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值