不要问为什么没有G,因为G我还没搞明白,我是蒟蒻,补药降维打击窝
A. Preparing for the Olympiad
思路:我们要让差值最大,我们发现,ai做了,那么bi+1就要做,因此我们可以去遍历整个数组,去寻找ai>bi+1的即可,然后累加起来差值就是最终结果
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n;
int a[200005];
int b[200005];
string s;
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
cin>>b[i];
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(a[i]>b[i+1])
ans+=a[i]-b[i+1];
}
cout<<ans<<"\n";
for(int i=1;i<=n;i++)
{
a[i]=b[i]=0;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
solve();
}
return 0;
}
B. Journey
思路:纯模拟的一道水题吧,先把总和求出来,看总共能走多少个三天,然后逐渐减,判断最后的结果
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n;
int a, b, c;
void solve() {
cin >> n >> a >> b >> c;
int mod=n%(a+b+c);
int time = n/(a+b+c)*3;
if(mod>0)
{
mod-=a;
time++;
}
if(mod>0)
{
mod-=b;
time++;
}
if(mod>0)
{
mod-=c;
time++;
}
cout << time << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
while (t--) {
solve();
}
return 0;
}
C. Preparing for the Exam
思路:这题我们发现可以分三种情况
1.q等于n,说明所有的答案都能拿到,那么我们m份试卷都应当为1
2.q<n-1 ,说明我们至少缺了两份答案,无论做哪个试卷都是0
3q=n-1,说明我们缺了一份试卷,我们找到缺的那个试卷,当mi为缺的那个试卷的标号的时候结果就是1,否则就是0
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n, m, k;
vector<int> a(300005);
vector<int> q(300005);
vector<int> vis(300005);
void solve()
{
for(int i=1;i<=n;i++)
{
vis[i]=0;
}
cin >> n >> m >> k;
for (int i = 1; i <= m; i++)
{
cin >> a[i];
}
for (int i = 1; i <= k; i++)
{
cin >> q[i];
vis[q[i]] = 1;
}
if (k >= n)
{
cout << string(m, '1') << "\n";
return;
}
else if (k < n - 1)
{
cout << string(m, '0') << "\n";
return;
}
else
{
int flag = 0;
for (int i = 1; i <= n; i++)
{
if (vis[i] == 0)
{
flag = i;
break;
}
}
for (int i = 1; i <= m; i++)
{
if (a[i] == flag)
{
cout << 1;
}
else
{
cout << 0;
}
}
cout << "\n";
return;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
while (t--)
{
solve();
}
return 0;
}
D. Counting Pairs
思路:我们去枚举要用到的点,然后去算出另外一个点的取值范围(上界和下界)
然后去二分查找上界和下界的坐标,然用坐标之差即为可用的数字,但是我们同时要注意减去自己与自己匹配的情况,因为左右边界可能会覆盖当前这个点的值
减去之后除2即为最终结果
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n, x, y;
int a[200005];
void solve()
{
cin >> n >> x >> y;
int sum = 0;
for (int i = 0; i < n; i++)
{
cin >> a[i];
sum += a[i];
}
sort(a, a + n);
int ans = 0;
int tong = 0;
for (int i = 0; i < n; i++)
{
int L = sum - y;
int R = sum - x;
int left = lower_bound(a, a + n, L - a[i]) - a;
int right = upper_bound(a, a + n, R - a[i]) - a;
if(left <= i && right > i)
{
tong++;
}
ans += (right - left);
}
cout << (ans - tong) / 2 << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
while (t--)
{
solve();
}
return 0;
}
E. Best Price
思路:这题看数据就知道要离散化一下,但是呢,我们可以将其存进vector里面,这样来处理离散化的操作,我们可以对a进行排序,对b进行排序,然后将a,b的数值存进一个set里面,这样可以完成去重的操作,然后去遍历这个set里面的数值,然后去计算有多少购买的人,如果差评数小于k即可进行计算最大值
我们这里来分析一下为什么用数组中的数就可以了,因为假设数组中没有p这个值,但是p+1在这个数组中,我们完全可以用p+1来代替p,来获得更大的收益,反之亦然,假设数组中有p这个元素p的下一个元素为q,假设p+1不为q,我们完全可以用q来代替p+1,来获得更大的收益,因为购买的人数是一样的
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n, k;
void solve()
{
cin >> n >> k;
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];
}
sort(a.begin(), a.end());
sort(b.begin(), b.end());
vector<int> v = a;
v.insert(v.end(), b.begin(), b.end());
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
int maxn = 0;
for(auto p : v)
{
int flag = n - (lower_bound(a.begin(), a.end(), p) - a.begin());
int sum = n - (lower_bound(b.begin(), b.end(), p) - b.begin());
int z = sum - flag;
if(z <= k)
{
int cnt = flag + z;
int ans = p * cnt;
maxn = max(maxn, ans);
}
}
cout << maxn << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
solve();
}
return 0;
}
F. Joker
思路:这题的思维很巧妙,在看到数据之前,一开始我想的是要搜索,就是去遍历两种选择的情况,后来一看数据直接给我劝退了,因此就要去想另一种操作了,我们并不一定就要去求出具体的值是哪个,我们可以用区间来转换这道题目
我们来分析一下三种可能的情况
假设x为我们的小丑牌,o为正常牌,我们将选择的牌标红来区别
假设我们当前的区间范围为{m,m}
1.我们选择的牌是小丑牌区间左边的牌
ooxoo
那么我们经过操作可能出现的范围为{m-1,m}
2.我们选择的小丑牌区间右边的牌
ooxoo
那么我们经过操作可得到的范围为{m,m+1}
3.我们选择的是小丑牌区间内的数
(1)同样分两种情况,一种是小丑牌区间长度不为1
oooxxxooo
那么我们可以分出来三个区间
{1,1},{l,r},{n,n}
(2)小丑牌区间长度为1
oooxooo
可以分出来两个区间
{1,1},{n,n}
有可能区间会重叠,那我们就更新前面那个区间的右端点即可,这样维护更加便捷
那么我们的思路就找到了,直接开写即可,
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pb push_back
#define pii pair<int,int>
int n,m,q;
int flag;
void solve()
{
cin>>n>>m>>q;
vector<pii> p;
p.push_back({m,m});
for(int i=1;i<=q;i++)
{
cin>>flag;
vector<pii> copy;
for(auto u:p)
{
int a=u.first;
int b=u.second;
if(flag<a)
{
copy.push_back({a-1,b});
}
else if(b<flag)
{
copy.push_back({a,b+1});
}
else
{
copy.push_back({1,1});
copy.push_back({n,n});
if(a!=b)
{
copy.push_back({a,b});
}
}
}
sort(copy.begin(),copy.end());
p.clear();
for(auto u:copy)
{
int a=u.first;
int b=u.second;
if(p.empty()||p.back().second<a)
{
p.push_back({a,b});
}
else
{
p.back().second=max(p.back().second,b);
}
}
int ans=0;
for(auto u:p)
{
int a=u.first;
int b=u.second;
ans+=(b-a+1);
}
cout<<ans<<" ";
}
cout<<"\n";
return;
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}