A - Digit Machine

Code

#include <bits/stdc++.h>
using namespace std;
 
int n, x, a[10];
 
int main()
{
    while (cin >> x)    a[n++] = x;    
 
    int t = 0;
    for (int i = 1; i <= 3; i++)
    {
        t = a[t];
    }
 
    cout << t;
    return 0;
}

B - Pasta

Code

#include <bits/stdc++.h>
using namespace std;
 
int n, m;
unordered_map<int, int> cnt;
 
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		int x;
		cin >> x;
		cnt[x]++;
	}	
	
	while (m--)
	{
		int x;
		cin >> x;
		if (cnt[x] > 0)	cnt[x]--;
		else 
		{
			puts("No");
			return 0;
		}
	}
	puts("Yes");
}

C - Connect 6

解题思路

1.枚举每个格子构成的6 * 6 网格(注意处理边界问题)
2.只有当横、竖或者两条对角线的黑色方格数>= 4时,才可以成功(因为最多涂黑两个方格)

方格图对角线元素点击此处查看,加深理解
TIPS:下面代码枚举反对角线时是构某个格子的右上方6 * 6网格
OS:很难想象学了这么久我竟然都不会枚举正、反对角线元素,我是rz

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;

int n;
string g[N];

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++) cin >> g[i];

    bool ans = false;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
        {
            if (i + 5 < n) 
            {
                int cnt = 0;
                for (int k = 0; k < 6; k++) 
                    if (g[i + k][j] == '#') cnt++;
                if (cnt >= 4)   ans = true;
            }
            if (j + 5 < n)
            {
                int cnt = 0;
                for (int k = 0; k < 6; k++)
                    if (g[i][j + k] == '#') cnt++;
                if (cnt >= 4)   ans = true;
            }
            if (i + 5 < n && j + 5 < n)
            {
                int cnt = 0;
                for (int k = 0; k < 6; k++)
                    if (g[i + k][j + k] == '#') cnt++;
                if (cnt >= 4)   ans = true;
            }
            if (i - 5 >= 0 && j + 5 < n)
            {
                int cnt = 0;
                for (int k = 0; k < 6; k++)
                    if (g[i - k][j + k] == '#') cnt++;
                if (cnt >= 4)   ans = true;
            }
        }

    if (ans)    puts("Yes");
    else puts("No");
    return 0;
}

D - Sequence Query(Multiset + 二分)

题目描述

我们有一个空序列。
给定Q个查询,按顺序处理它们。
每个查询属于以下三种类型之一。
1 x:将 x插入到 A
2 x k:找到小于等于x的集合中第k大的数
3 x k:找到大于等于x的集合中第k小的数
数据范围:
$1 \le Q \le 2 * 10 5$
$1 \le x \le 10
18$
$1 \le k \le 5$

解题思路

本题用到了multiset数据结构,可以做到让元素从小到大排序,并且可以重复
然后再结合multiset自带的二分查找($O(logn)$)给定的元素
分情况:
1. 对于op == 2的操作, 使用upper_bound找大于元素x的第一个位置,然后往前找,次数为k
2. 对于op == 2的操作, 使用lower_bound找大于等于元素的第一个位置,然后往后找,由于这个位置已经符合条件,所以次数为k - 1

OS: 比赛的时候没有正确分析复杂度,思路很接近正解,但是没有用二分。 被很多题解被迷惑了,导致补题的时候被卡了两个小时!

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
bool flag;
ll q, op, x, k;
multiset<long long> s;
 
int main()
{
	cin >> q;
	while (q--)
    {
		cin >> op >> x;
		if (op == 1) s.insert(x);
		else if (op == 2)
        {
			cin >> k;
			auto it = s.upper_bound(x);
			flag = true;
			
            for (int i = 1; i <= k; i++)  // 每次都移动it指针
            {
				if (it == s.begin()) flag = false;  // 只有当当前元素不是begin(), 才说明前面还有元素
				else --it;  // 前面还有元素,所以--
			}
			if (flag)    cout << *it << endl;  
			else puts("-1");
		}
		else
        {
			cin >> k;
			auto it = s.lower_bound(x);
			flag = true;
 
			for (int i = 1; i < k; i++)   // 由于找到的这个位置已经符合条件,所以次数为 k - 1
            {
				if (it == s.end())   flag = false;  // 如果到了末尾,就置为false
				else ++it;  // 只有不是末尾时,才++; 在 i == k时,有可能这一次移动导致移到了end,所以有了下面的特判
			}
			if (it == s.end())   flag = false;  // 特判最后一个元素, 因为可能最后一次移动到了end
			if (flag)   cout << *it << endl;
			else puts("-1");
		}
	}
	return 0;
}

E - Putting Candies

题目描述

avatar

解题思路

OS:以后再补吧,没时间咯
详细题解参考此处

F - Skate(BFS)

题目描述

avatar

解题思路

经观察可得,只有障碍物的四周能达到
所以我们只需要分别对行、列枚举障碍物的四周
用二分查找到同行同列的元素,并进行判断
如果每次能找到符合条件的元素的话,就在原先的基础上距离 + 1
详细题解参考此处

Code

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N = 100010;
typedef pair<int, int> PII;

int h, w, n, sx, sy, ex, ey;
map<PII,int> vis;
PII row[N], col[N];
struct node
{
	int x, y, d;
};

int BFS()
{
	queue<node> q;
	q.push({sx, sy, 0});
	
	while (q.size())
	{
		auto t = q.front();
		q.pop();
        if (vis[{t.x, t.y}]) continue;
        vis[{t.x, t.y}] = 1;
		
		if (t.x == ex && t.y == ey) return t.d;
		
		auto it = lower_bound(row + 1, row + n + 1, PII {t.x, t.y});  // 在同行中变换列
		int tx = it->x, ty = it->y;
		if (t.x == tx && t.y != ty - 1) q.push({tx, ty - 1, t.d + 1});

		it--;
	    tx = it->x, ty = it->y;
	    if (t.x == tx && t.y != ty + 1)	q.push({tx, ty + 1, t.d + 1});   	

		it = lower_bound(col + 1, col + n + 1, PII {t.y, t.x});  // 在同列中变换行
		ty = it->x, tx = it->y;
		if (t.y == ty && t.x != tx - 1)	q.push({tx - 1, ty, t.d + 1});	
		
		it--;   
		ty = it->x, tx = it->y;
		if (t.y == ty && t.x != tx + 1)	q.push({tx + 1, ty, t.d + 1});	
	}
	return -1;	
}

int main()
{
	cin >> h >> w >> n;
	cin >> sx >> sy >> ex >> ey;
	for (int i = 1; i <= n; i++)  // 从1读可以保证row,col中有{0,0}以免--it出现边界问题
	{
		int r, c;
		cin >> r >> c;
		row[i] = {r, c};
		col[i] = {c, r};
	}
	sort(row + 1, row + 1 + n); sort(col + 1, col + 1 + n);
	
	cout << BFS() << endl;
	return 0;
}

上一篇 下一篇