A - Scoreboard
题意
给你n场比赛的结果
每一场比分 x:y 对应两个人的分数
要求输出n场总得分较高的队伍名称
若平局则输出“Draw”
思路
相加比较即可
code
#include<iostream>
#include<algorithm>
#include<map>
#include<cmath>
#include<set>
#include<vector>
#include<queue>
//#define int long long
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
const int M = 220;
int a[M];
int cnt1,cnt2;
void solve()
{
int a,b; cin >> a >> b;
cnt1 += a,cnt2 += b;
}
int main(){
ios::sync_with_stdio(0); cin.tie(0),cout.tie(0);
int t; cin >> t;
int tt = t;
while(t --) solve();
if(cnt1 > cnt2) cout << "Takahashi";
else if(cnt1 < cnt2) cout << "Aoki";
else cout << "Draw";
return 0;
}
B - Extended ABC
题意
给你一个字符串只包含ABC 要求出现的顺序严格满足 A -> B -> C
在这个情况下可以满足输出Yes 否则No
思路
只要找到一个不满足的就行 也就是说
1. 在出现A之前不能出现B,C
2. 在出现B之前不能出现A
都满足就Yes
code
#include<iostream>
#include<algorithm>
#include<map>
#include<cmath>
#include<set>
#include<vector>
#include<queue>
//#define int long long
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
const int M = 220;
int cnt1,cnt2;
void solve()
{
string a; cin >> a;
int length = a.size();
bool st1 = false,st2 = false,st3 = false;
for(int i = 0;i < length;i ++)
{
if(a[i] == 'A') st1 = true;
if(a[i] == 'B') st2 = true;
if(a[i] == 'C') st3 = true;
if(st2 || st3)
{
if(a[i] == 'A')
{
cout << "No\n";
return;
}
}
if(st3)
{
if(a[i] == 'B' || a[i] == 'A')
{
cout << "No\n";
return;
}
}
}
cout << "Yes\n";
}
int main(){
ios::sync_with_stdio(0); cin.tie(0),cout.tie(0);
int t = 1;
while(t --) solve();
return 0;
}
C - Lining Up 2
题意
给你一个序列的长度N和序列A,表示一群人在排队买他们最爱的糯叽叽
规则如下:
1. 如果Ai = -1 表示 i 排在队列的最前面
2. 否则 i 紧跟在 Ai后面
现在要你还原真实队列顺序
思路
当时用的set容器想着这样找好快好省心
找到了存一个下标就行了
后来想想用链表就行了
code
#include<iostream>
#include<algorithm>
#include<map>
#include<cmath>
#include<set>
#include<vector>
#include<queue>
//#define int long long
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 3e5 + 10;
int a[N];
void solve()
{
set<PII> se;
int n; cin >> n;
int shou = 0;
for(int i = 1;i <= n;i ++)
{
int x; cin >> x;
if(x == -1) shou = i;
se.insert({x,i});
}
int idx = 1;
a[idx++] = shou;
PII now = {shou,0};
while(idx <= n)
{
auto tmp = se.lower_bound(now);
now = {tmp->second,0};
a[idx ++] = tmp -> second;
}
for(int i = 1;i <= n;i ++) cout << a[i] << ' ';
}
int main(){
ios::sync_with_stdio(0); cin.tie(0),cout.tie(0);
int t = 1;
while(t --) solve();
return 0;
}
D - Cheating Gomoku Narabe
题意
给你一个字符矩阵的High,Width,一个长度K
表示你需要找到连续长K个字符,满足都是“。”(可以横着也可以竖着)
这个矩阵由('x','.','。')构成,像这样:
3 4 3 xo.x ..o. xx.o
你有一个魔法可以让 '.' 变成 '。' 但是对于'x'无计可施
现在你要找到满足连续的长度为K的序列,期间所用魔法数最少的,输出这个次数
思路
滑动窗口
横着的全来一遍
竖着的全来一遍
以横着的全来一遍为例:
现在你在第一行遍历,首先把窗口固定在最开始的k列,统计'x'和‘。’的个数,在到达边界之前每次往右滑动窗口的时候都对个数进行更新,每次更新的同时更新minid也就是魔法施加的最小次数
code
现在说正事
老想着用queue但是发现根本不需要只要统计次数就行
两个版的代码都放一下,前后可以对照
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
const int INF = 0x3f3f3f3f;
void solve()
{
int n,m,k; cin >> n >> m >> k;
// char a[n+10][m+10];
vector<vector<char>> a(n + 1, vector<char>(m + 1));
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= m;j ++)
cin >> a[i][j];
// rows
int minid = INF;
if(k <= m)
{
for(int i = 1;i <= n;i ++)
{
int cnt = 0;
// int cnt1 = 0;
queue<int> q;
for(int j = 1;j <= k;j ++)
{
// if(a[i][j] == 'x') cnt1 ++;
if(a[i][j] == 'x') q.push(j);
else if(a[i][j] == 'o') cnt ++;
}
// if(cnt1 == 0) minid = min(minid,k - cnt);
if(q.empty()) minid = min(minid,k - cnt);
for(int j = k + 1;j <= m;j ++)
{
// if(a[i][j] == 'x') cnt1 ++;
if(a[i][j] == 'x') q.push(j);
else if(a[i][j] == 'o') cnt ++;
// if(a[i][j-k] == 'x') cnt1 --;
if(a[i][j-k] == 'x') q.pop();
else if(a[i][j-k] == 'o') cnt --;
// if(cnt1 == 0) minid = min(minid,k-cnt);
if(q.empty()) minid = min(minid,k - cnt);
}
}
}
// columns
if(k <= n)
{
for(int j = 1;j <= m;j ++)
{
int cnt = 0;
// int cnt1 = 0;
queue<int> q;
for(int i = 1;i <= k;i ++)
{
// if(a[i][j] == 'x') cnt1 ++;
if(a[i][j] == 'x') q.push(j);
else if(a[i][j] == 'o') cnt ++;
}
// if(cnt1 == 0) minid = min(minid,k - cnt);
if(q.empty()) minid = min(minid,k - cnt);
for(int i = k + 1;i <= n;i ++)
{
// if(a[i][j] == 'x') cnt1 ++;
if(a[i][j] == 'x') q.push(j);
else if(a[i][j] == 'o') cnt ++;
// if(a[i-k][j] == 'x') cnt1 --;
if(a[i-k][j] == 'x') q.pop();
else if(a[i-k][j] == 'o') cnt --;
// if(cnt1 == 0) minid = min(minid,k-cnt);
if(q.empty()) minid = min(minid,k - cnt);
}
}
}
if(minid < INF) cout << minid << '\n';
else cout << "-1" << '\n';
}
int main()
{
IOS;
int tt; tt = 1;
while(tt --) solve();
return 0;
}
E - Bad Juice
题意
一道交互题
你有N瓶果汁 有一瓶变质了但你不知道是哪个 果汁有自己的标志 1,2,3,...,N。
你决定送给朋友一些瓶,你怎么给朋友都行,每个人收到的数量也不限。
Judge先生会告诉你送的那些朋友第二题喝完你送的果汁后有没有拉肚子。
用一个01串来表示 1代表拉肚子 也就是喝到了变质的饮料。
现在要你结合给你的N来决策:
你需要给几个朋友(你有无数个朋友)以及给他们哪几个果汁
还要结合Judge先生反馈的01串:
找到到底是哪瓶果汁变质了。
思路
假定给的N 转化为2进制后
你会发现N有几位你就需要给几个朋友
因为它的每一位都可以让一个朋友来承担
比如 N = 6 二进制表示成 110
那么果汁的下标是 001 010 011 100 101 110
那么你需要3个朋友
第一个朋友负责
第一个朋友负责第0位:3 bottles index=1,3,5
第二个朋友负责第1位:2 bottles index=2,6
第三个朋友负责第1位:2 bottles index=4,6
假如判官给的110那就证明 第二、三个朋友拉肚子 答案是6 也就是110
之所以这样是因为你的朋友就是代表了位数
特别的对于2次幂来说有一个最高位是不需要判断的 按上面的逻辑却被判断进去了
所以只需要在最开头统计位数的时候少统计一位
如果法官全给0 那就证明就是二次幂那个数 直接输出N即可
code
#include<iostream>
#include<cstdio>
#include<stack>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstring>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long long
//#define double long double
//#define PI acos(-1.0)
using namespace std;
typedef long long ll;
//const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
//typedef pair<char, int> PCI;
void solve()
{
int n; cin >> n;
int m = 0;
while ((1ll << m) < n) m++;// 1算0位 4算2位 因为后面是从0开始算的
cout << m << endl;
for (int i = 0; i < m; i++)
{
vector<int> ve;
for (int j = 1; j <= n; j++)
if ((j >> i) & 1) ve.push_back(j);
cout << ve.size() << ' ';
for (auto it : ve) cout << it << ' ';
cout << endl;
}
string st; cin >> st;
int res = 0;
for (int i = 0; i < m; i++)
{
if (st[i] == '1') res += (1ll << i);
}
if (res == 0) cout << n << endl;
else cout << res << endl;
}
signed main()
{
IOS;
int tt = 1;
while (tt--) solve();
return 0;
}