A题(字符串处理和使用find()函数)
题意:给定01串 s , 找出01串 t ,其中 t 满足在串 s + t + s 中,s串仅出现两次。
思路:我们可以由题目看出,我们只需要找全0串或者全1串即可,因为如果在 s000..s中,除了开头两个 s 之外中间还出现过 s ,那么一定是需要 0 的, 我们只需要全是 1 即可,反之亦然。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<unordered_map>
#include<set>
#include<stack>
#include<cmath>
#include<unordered_set>
//#define int unsigned long long
#define int long long
using namespace std;
const int N = 1010, P = 131;
void solve()
{
int n;
string s;
cin >> n >> s;
int ze = 0, on = 0;
for (int i = 0; i < s.size(); ++ i)
{
if(s[i] == '0') ze = 1;
else on = 1;
if(on && ze) break;
}
if(ze && !on)
{
for (int i = 0; i < n; ++ i) cout << 1;
}
else if(!ze && on)
{
for (int i = 0; i < n; ++ i) cout << 0;
}
else
{
string z = "";
for (int i = 0; i < n; ++ i) z += "0";
string a = " " + s + z + s;
a.erase(a.begin() + 1);
a.erase(a.end() - 1);
if(a.find(s) == string::npos) cout << z;
else
{
for (int i = 0; i < n; ++ i) cout << 1;
}
}
cout << endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while(T--)
{
solve();
}
return 0;
}
F题(可模拟,考中我使用了二分(其实没必要))
题意:题意就是给一个序列每次选和他绝对值差最大的去除,有相等的取右边的值。
思路:我们可以看到,本题每次去除的,其实就是数组的最小或最大,那么我们直接判断谁的票多即可,赛后发现其实直接求处理中位数即可,赛中我使用的是二分来判断。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<unordered_map>
#include<set>
#include<stack>
#include<cmath>
#include<unordered_set>
#define int long long
using namespace std;
const int N = 1e6 + 10;
int a[N];
unordered_map<int, int> ans;
void solve()
{
int n;
cin >> n;
for (int i = 1; i <= n; ++ i)
{
cin >> a[i];
ans[a[i]] = i;
}
sort(a + 1, a + n + 1);
if(n <= 2) cout << 1 << endl;
else
{
int he = 1, ta = n;
while(he + 1 <= ta - 1)
{
int l = he + 1, r = ta - 1;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(a[ta] - a[mid] >= a[mid] - a[he]) l = mid;
else r = mid - 1;
}
if(a[ta] - a[l] < a[l] - a[he]) l --;
if(l - he + 1 >= ta - l) ta --;
else he ++;
}
cout << ans[a[he]];
}
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// int T;
// cin >> T;
// while(T--)
// {
solve();
// }
return 0;
}
L题(思维)
题意:有一组 n 行 m 列的灯,最初灯都是关的。有q 次操作,每次操作为:①打开第 i 行的灯;②关掉第 i 行的灯;③打开第 i 列的灯;④关掉第 i 列的灯。问最终亮着的灯有多少盏?
思路:我们知道,如果对于同一盏灯,无论前面对他进行过多少开关处理,只有最后一个影响到它的处理有用,所以我们直接逆序遍历即可。
代码:
#include <iostream>
using namespace std;
const int N = 1e6+10;
struct Node{
string op1,op2;
int x;
}node[N];
int st1[N],st2[N];
int main()
{
int n, m, q;
cin>>n>>m>>q;
for(int i=1;i<=q;i++){
cin>>node[i].op1>>node[i].x>>node[i].op2;
}
long long ans=0;
for(int i=q;i;i--){
if(node[i].op1=="row"){
if(!st1[node[i].x]){
st1[node[i].x]=1;
if(node[i].op2=="on"){
ans+=m;
}
n--;
}
}else{
if(!st2[node[i].x]){
st2[node[i].x]=1;
if(node[i].op2=="on"){
ans+=n;
}
m--;
}
}
}
cout<<ans;
return 0;
}