题目链接 戳这
本文章将持续更新。
A.Permutation Grid
题目大意:第一行给定一个n的排列R1…Ri…Rn,表示第i行有几个"#", 下一行给定1-n的另一个排列C1…Cj…Cn,表示第j列有多少个“#”, 下面q个询问,问第x行y列是不是“#”。
猛的一看以为是构造,但看了大佬的代码,我更愿称其为规律吧。
以样例一为例,n=5时,我们一共有 1+2+3+4+5=15个“#”, 在两个排列中随机各抽一个相加,发现一共有15个的和是大于5的,正好为15个“#”。(但具体为什么我也没想大清楚,希望大佬可以指教)
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#define y second
#define x first
using namespace std;
typedef long long LL;
int main(void)
{
int n;
cin >> n;
vector<int> a(n);
for(int i = 0; i < n; i ++) cin >> a[i];
vector<int> b(n);
for(int i = 0; i < n; i ++) cin >> b[i];
int q;
cin >> q;
while(q --)
{
int x, y;
cin >> x >> y;
if(a[x - 1] + b[y-1] > n) printf("#");
else printf(".");
}
puts("");
return 0;
}
B.Shift and Reverse
题目大意:给定一个1-你的排列,一共有两种操作:第一种:翻转整个序列,第二种:将第一个数挪到最后。求将整个序列变为增序的最小操作步数。题目保证给出的排列是可以通过这两种将排列变为升序的,即保证有解。
随便给出一个排列,都可将其看成一个环,两种操作只是改变了起点或者逆时针和顺时针顺序。如上图所示,这种序列是无解的。有解的是下面这种环:
我们根据顺逆时针来讨论两种情况即可。我们找到1的位置idx_1,看下一位是不是2即可。
- 顺时针:两种方法(1)将1前面的数依次挪到后边,操作次数idx_1次; (2)例如当序列是2 3 4 5 1时,我们最优操作是先将整个序列翻转:1 5 4 3 2 ,再将1挪至末尾,在将整个序列反转: 1 2 3 4 5, 所需操作是3.
详见代码:操作次数是n - idx + 2 - 逆时针:例如2 1 5 4 3(1)将1挪至末尾:idx + 1次,再将整个序列反转 1, 一共idx+2次 (2)先将整个序列翻转:3 4 5 1 2,再将1前边挪到末尾:n-idx-1一共是n-idx次。
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
vector<int> vec(n);
bool flag = false; //顺时针记为true
for(int i = 0; i < n; i ++) cin >> vec[i];
int ans = n;
int idx_1;
for(int i = 0; i < n; i ++)
{
if(vec[i] == 1) idx_1 = i;
}
if(vec[(idx_1 + 1) % n] == 2) flag = true;
if(flag) ans = min(idx_1, n - idx_1 + 2);
else ans = min(n-idx_1, idx_1 + 2);
cout << ans << endl;
// cout << flag << endl;
return 0;
}