A. Hard Way

Code

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<double, double> PDD;

void solve()
{
	PDD p[5];
	for (int i = 1; i <= 3; i++)	cin >> p[i].y >> p[i].x;
	sort(p + 1, p + 1 + 3);
	
	if (p[3].x == p[2].x)	printf("%.9lf\n", abs(p[3].y - p[2].y));
	else cout << 0 << endl;
}

int main()
{
	int T;
	cin >> T;
	while (T--)	solve();
	return 0;    
}

B. Power Walking

Code

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

void solve()
{
    
    int n; cin >> n;
    set<int> s;
    
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        s.insert(x);
    }

    for (int i = 1; i <= n; i++)    cout << max(i, int(s.size())) << ' ';
    cout << endl;
}

int main()
{
	int T;
	cin >> T;
	while (T--)	solve();
	return 0;    
}

C. Great Sequence

题目大意

题意:给定 $x$ ,在数组中添加尽可能少的数,使得数组可以分成若干对 $(p,q)$ ,数组中每个元素恰好在一个pair中。并且每个pair的 $p,q$ 满足:

  • $p = xq$

解题思路

将数组排序后从小到大枚举,如果存在一个数 $p$ ,必然需要有一个 $xq$ 与之配对,如果不存在,则答案加一;如果存在,则删去一个 $xq$ 。

供上自己的错误TLE做法(人生中第一次被hack!)

Code

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

ll n, x, t;

void solve()
{
    map<ll, ll> mp;  // 用map可以实现自动排序
    cin >> n >> x;
    
    for (int i = 1; i <= n; i++)
    {
        cin >> t;
        mp[t]++; 
    }

    ll res = 0;
    for (auto item : mp)
    {
        if (!mp.count(item.first * x))    res += item.second;  // 一次性全部加上
        else
        {
            mp[item.first * x] -= item.second;
            if (mp[item.first * x] < 0)  
            {
                res -= mp[item.first * x];  // 此时mp[item * x]为负数, '-'相当于加上操作次数
                mp.erase(item.first * x);  // 从map中删除这个元素
            } 
        }
    }
    cout << res << '\n';
}

int main()
{
    int T; cin >> T;
    while (T--) solve();
    return 0;
}

D. Repetitions Decoding

题目大意

给定一个长度为 $n(n < 500)$ 的数组,可以选择多次向数组中的同一位置插入相同的两个数。
最多执行 $2*n^2$ 次。满足操作后,可以将数组分为多个连续的子数组,每个子数组的长度都为偶数。
对于每个子数组,前一半等于后一半。比如 [1,1,4,1,1,4] , [5,1,4,5,1,4] 。
请输出方案。
方案的格式为
操作的次数。每次操作为:
$p,c$ 在第 $p$ 个元素的后面插入两个 $c$ 。
最后还需要输出分出的子数组的大小。

解题思路

严格鸽的题解把这题的思路讲的特别详细

另外,今天才注意到一个语法方面的东西
如果vector声明时后面没有跟‘(n)’类似的容量声明,则只能够用push_back来插入数据
否则直接用cin >> v[i]的话会因为容量不够而无法输入数据
举例:

  • vector<int> v; {int x,cin >> x, v.push_back(x)};
  • vector<int> v(n); {cin >> v[i]};

TIPS:代码中的删除操作不能交换,因为删除操作会使得迭代器失效的。
【C++ STL】迭代器失效的几种情况总结

Code

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;

void solve()
{   
    int n, tot = 0;  // 统计已经删除的数的个数
    cin >> n;
    vector<int> v(n), siz;  // 最后方案中每个子数组的长度
    vector<PII> ans;
    unordered_map<int, int> cnt;
    
    
    for (int i = 0; i < n; i++)  cin >> v[i], cnt[v[i]]++;

    for (auto x : cnt)  
		if (x.second % 2) 
        {
            cout << -1 << '\n'; 
            return;
        }   

    for (int i = 1; i <= n / 2; i++)
    {
        auto it = ++v.begin();
        while (*it != *v.begin()) it++;

        int dist = it - v.begin();
        for (int j = 0; j < dist - 1; j++) ans.push_back({tot + dist + 1 + j, v[j + 1]});

        reverse(v.begin() + 1, it);  // 反转中间的序列
        v.erase(it);  // 删除后面一个元素, 这里不能交换删除顺序
        v.erase(v.begin());  // 删除开头的元素

        tot += dist * 2;
        siz.push_back(dist * 2);
    }   

    cout << ans.size() << '\n';
    for (auto x : ans)  cout << x.first << ' ' << x.second << '\n';
    cout << siz.size() << '\n';
    for (auto x : siz)  cout << x << ' ';
    cout << '\n';
}

int main()
{
    int T;
    cin >> T;
    while (T--) solve();
    return 0;
}

上一篇 下一篇