题目链接:topic
A、B题均为签到题,在此不做过多阐释。
A. Plus or Minus
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin.tie(0);cout.tie(0);
int n;cin>>n;
while(n--)
{
int a,b,c;
cin>>a>>b>>c;
if(a+b==c) cout<<"+\n";
else cout<<"-\n";
}
return 0;
}
B. Grab the Candies
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--)
{
int n,num,even=0,odd=0;
cin>>n;
while(n--)
{
cin>>num;
if(num%2==0) even+=num;
else odd+=num;
}
if(even>odd) cout<<"Yes\n";
else cout<<"No\n";
}
return 0;
}
C. Find and Replace
题目分析:本题的核心是判断字符串中所有不同位置的同一小写字母之间的距离是否都为奇数,若有偶数存在,则无法构成交替排列的二进制序列。
解题思路:首先考虑位置的奇偶性,(字符串索引排序从0开始)假设字符a此时所在的位置索引为奇数,则下一个a出现的位置对应位置索引同样为奇数的时候,二者之间的距离满足奇数个;同理,当a字符的位置索引为偶数的时候,则下一个a出现的位置对应位置索引同样为偶数时满足。
综上所述,我们只需要用一个数组记录不同字符的位置奇偶性,遍历整个字符串,若满足不同字符对应的所有同类型字符位置奇偶性相同即可满足要求,否则不满足要求。
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int len;
string s;
cin>>len>>s;
int f[26];
for(int i=0;i<26;i++) f[i]=-1;
for(int i=0;i<len;i++)
{
int index=s[i]-'a';
if(f[index]==-1) f[index]=i%2;
else
{
if(f[index]!=(i%2)) {cout<<"No\n";return;}
}
}
cout<<"Yes\n";
}
int main()
{
ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--){solve();}
return 0;
}
D. Odd Queries
题目分析:本题核心是判断改变后的数组元素总和的奇偶性,若为奇则满足条件,否则不满足条件。
解题思路:题目的思路很简单,但是题目给的数据范围会很大,为了防止超时,采用前缀和的思想,并用long long 记录数据。对于每一次数值的改变,相当于将第l到第r项的所有元素归零,也就是sum-(add[r]-add[l-a]),并在此基础上加上(r-l+1)个k即可。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
long long a[N],add[N];
void solve()
{
long long n,q;
cin>>n>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
add[i]=add[i-1]+a[i];
}
while(q--)
{
long long l,r,k;
cin>>l>>r>>k;
long long sum=add[n]-(add[r]-add[l-1])+(r-l+1)*k;
if(sum%2==1) cout<<"Yes\n";
else cout<<"No\n";
}
}
int main()
{
ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--){solve();}
return 0;
}
E. Interview
题目分析:本题是一个人机交互问题(interative problem),详细可以参考Guide for Particioants。交互问题一般都用二分解法,回答分为两种情况,判断堆是否在当前k堆之中,二分所问次数为⌈log2(2⋅1e5)⌉=18<30。因此本题的核心是如何构建二分判断。
解题思路:首先,在输入每堆数目的时候我们用前缀和记录数据,用于之后的二分判断,n/2进行判断,直到只剩下唯一的一堆结束。判断条件是l到mid的所有堆数总和是否等于回答的值,若非,则为true,否则为false,由此进行区间更迭,直到结束。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N],add[N];
void solve()
{
int n;cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
add[i] = add[i - 1] + a[i];
}
int l = 1, r = n,res=0;
while (l <= r)
{
int mid = l + r >> 1;
cout << "? " << (mid - l + 1) << ' ';
for (int i = l; i <= mid; i++) cout << i << ' ';
cout << endl << flush;
int ans=0;
cin >> ans;
if (add[mid] - add[l - 1] == ans) l = mid + 1;
else {
r = mid - 1;
res = mid;
}
}
cout << "! " << res << endl << flush;
}
int main()
{
ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t;cin >> t;
while (t--){solve();}
return 0;
}
F. Bouncy Ball
题目分析:本题是一个图像问题,需要理解小球反弹的条件与判断小球是否能够到达重点。
解题思路:首先将DR、DL、UR、UL看做坐标加减运算,将图表看做坐标系,因此当(x1,y1)与(x2,y2)重合时满足条件。
#include <bits/stdc++.h>
using namespace std;
void solve()
{
int n,m,x1, y1, x2, y2;
string str;
cin >> n >> m >> x1 >> y1 >> x2 >> y2 >> str;
int dx = 1, dy = 1;
if (str[0] != 'D') dx = -1;
if (str[1] != 'R') dy = -1;
int ans = 0;
while (!((x1 == x2) && (y1 == y2)))
{
int num = 0;
if (x1 + dx<1 || x1 + dx>n) dx = -dx, ans++,f++;
if (y1 + dy<1 || y1 + dy>m) dy = -dy, ans++,f++;
x1 += dx; y1 += dy;
if (num == 2) ans--;
if (ans > n * m)
{
cout << "-1\n";
return;
}
}
cout << ans << endl;
}
int main()
{
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t; cin >> t;
while (t--) { solve(); }
return 0;
}
G1. Subsequence Addition (Easy Version)
G1、G2的区别在于G2的数据限制范围更大,对算法时间效率要求更高,因此考虑贪心的算法。G1采用暴力DP的方法处理(用于G2会超时)。
#include<bits/stdc++.h>
using namespace std;
const int N=5010;
int a[N];
void solve()
{
int n;cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
if(a[1]!=1)
{
cout<<"No\n";
return;
}
vector<int>f(N,0);
f[1]=1;
for(int i=2;i<=n;i++)
{
if(!f[a[i]])
{
cout<<"No\n";
return;
}
for(int j=5000;j>=a[i];j--) f[j]|=f[j-a[i]];
}
cout<<"Yes\n";
return;
}
int main()
{
ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--){solve();}
return 0;
}
G2. Subsequence Addition (Hard Version)
#include <bits/cstdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N];
void solve()
{
int n; cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
sort(a, a + n);
if (a[0] != 1)
{
cout << "No\n";
return;
}
long long sum = a[0];
for (int i = 1; i < n; i++)
{
if (sum < a[i])
{
cout << "No\n";
return;
}
sum += a[i];
}
cout << "Yes\n";
return;
}
int main()
{
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t; cin >> t;
while (t--) { solve(); }
return 0;
}