平时总是懈怠,明明决定要认真做的事情一直拖延一直玩。所以在博客记录下来我一天做题的记录,这样或许能帮助我更好完成我的学习任务和学业。
8.9-8.19之间,每天完成三场div3的训练,补题数以一场两题为界限,如果两题内包含超过1900分分看知识点,如果知识点学过补,没学过不补。
8.9号的没记录,现在从8.10号的开始记录。
1.round 895 div3 1
a.Two Vessels
思路:贪心尧水
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin >> t;
while(t--)
{
int a,b,c;
cin >> a >> b >> c;
c*=2;
int num=abs(a-b);
cout << (num%c==0 ? num/c : num/c+1) << endl;
}
return 0;
}
2.The Corridor or There and Back Again
思路:贪心找到每一个陷阱的最远行驶距离然后取max
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin >> t;
while(t--) {
int n;
cin >> n;
int min_v=0x3f3f3f3f;
for(int i=1;i<=n;i++) {
int d,t;
cin >> d >> t;
min_v=min(min_v,d+(t-1)/2);
}
cout << min_v << endl;
}
return 0;
}
3.Non-coprime Split(补1)
思路:gcd有性质:gcd(a,b)若a>b有gcd(a-b,b)==gcd(a,b),所以我只要找到l到r范围里面是不是有一个数有因数,如果有那么我就可以通过构造 (因数,i-因数) 【i是有一个数的这个数】来构造我的一个正确解法。(代码里的偶数情况其实可以包含在这个解法里面)
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin >> t;
while(t--) {
int l,r;
cin >> l >> r;
bool flag=false;
for(int i=l;i<=r;i++) {
if(i%2==0 && i!=2) {
flag=true;
cout << 2 << " " << i-2 << endl;
break;
}else {
for(int j=2;j*j<=i;j++)
{
if(i%j==0) {
if(i-j>=0) {
cout << j << " " << i-j << endl;
flag=true;
break;
}
}
}
}
if(flag) break;
}
if(!flag) cout << -1 << endl;
}
}
4.
因为cf崩了一个下午加一个晚上,计划失败
8.11
1.round 894 div3 2
找输入的数组里面是不是有从前往后四个不同列中分别有vike,暴力找就好了,但是我写的代码有点太暴力了,还好只有四个字母,题解给的代码和我的意思一样,但是pos的地方改成了如果成功累加其实这样能少写很多加快速度。
#include <bits/stdc++.h>
using namespace std;
const int N=25;
string S[N];
int main()
{
int t;
cin >> t;
while(t--) {
int n,m;
cin >> n >> m;
for(int i=1;i<=n;i++) {
cin >> S[i];
}
bool pos1=0,pos2=0,pos3=0,pos4=0;
for(int i=0;i<S[1].size();i++) {
for(int j=1;j<=n;j++) {
// cout << S[j][i] << endl;
if(S[j][i]=='v' && !pos1) {
pos1=true;
break;
}
if(S[j][i]=='i' && pos1 && !pos2) {
pos2=true;
break;
}
if(S[j][i]=='k' && pos2 && !pos3) {
pos3=true;
break;
}
if(S[j][i]=='a' && pos3 && !pos4) {
cout << "YES" << endl;
pos4=true;
break;
}
if(pos4) break;
}
}
if(!pos4) cout << "NO" << endl;
}
return 0;
}
构造题,但是要注意范围,不能小于1,所以直接扫一遍如果比前面的数小vector插入一个自己就好了。
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int B[N];
int main()
{
int t;
cin >> t;
while(t--) {
int n;
cin >> n;
vector<int> A;
for(int i=1;i<=n;i++) {
cin >> B[i];
if(B[i]<B[i-1]) {
A.push_back(B[i]);
}
A.push_back(B[i]);
}
cout << A.size() << endl;
for(auto t:A) {
cout << t << " ";
}
cout << endl;
}
}
c.Flower City Fence(补1)
其实是想到了,用差分,但是边界总是搞不清楚给自己搞晕了。就是输入的时候按照题意是一条条竖直的,然后可以对每一条竖直的进行差分,对差分数组前缀和后,每个B[i]存的就是对应i高度的厚度,然后再用这个厚度和我的原来A[i]数组比较看是不是相等就行。但是因为输入的时候我的A[i]的值是1e9非常容易爆我的f所以我应该特判一下。
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int A[N],S[N],B[N];
int main()
{
int t;
cin >> t;
while(t--) {
memset(S,0,sizeof S);
memset(B,0,sizeof B);
int n;
cin >> n;
bool flag=false;
for(int i=1;i<=n;i++) {
cin >> A[i];
if(A[i]>n && !flag) {
cout << "NO" << endl;
flag=true;
}
S[1]++;
if(!flag) S[A[i]+1]--;
}
if(flag) continue;
// cout << "where:" << flag << endl;
for(int i=1;i<=n;i++) {
B[i]=B[i-1]+S[i];
// cout << "B:" << B[i] << endl;
}
for(int i=1;i<=n;i++) {
if(A[i]!=B[i]) {
cout << "NO" << endl;
flag=true;
break;
}
}
if(!flag) cout << "YES" << endl;
}
return 0;
}
4.
2.round 820 div3 3
a和b都是裸贪心
c.Jumping on Tiles
要求给出头字母到尾字母中间的路径和花费(差值和距离),因为'a'->'c'和'a'->'b'->'c'相同花费,所以说尽可能多找两个字符的中间值。
我写的办法是开pair存值和i,排序后找到两个字母的左右区间然后输出出来,但是题目要求得从1开始结尾是|s|,这样导致我二分的边界有四个。我一开始没想这么多导致我即找不到错误在那里改了快一个小时。
还是尽可能能不二分不二分,官方题解采用的是找到左右两边界,用map存vector然后一个个找,这样特判找不容易错。
我的代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define x first
#define y second
typedef pair<int,int> PII;
const int N=2e5+10;
PII cnt[N];
int cnt1[N];
bool cmp(const PII &a,const PII &b) {
if(a.x!=b.x) {
return a.x<b.x;
}else {
return a.y<b.y;
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--) {
string s;
cin >> s;
for(int i=0;i<s.size();i++) {
cnt[i]={s[i]+1-'a',i+1};
}
sort(cnt,cnt+s.size(),cmp);
//复制到数组里用二分
for(int i=0;i<s.size();i++) {
cnt1[i]=cnt[i].x;
// cout << "cnt:" << cnt[i].x << " ";
}
int l=s[0]+1-'a',r=s[s.size()-1]+1-'a';
int n=s.size();
if(l==r) {
int rr;
int ll=lower_bound(cnt1,cnt1+n,l)-cnt1;
if(cnt[n-1].x!=r) rr=upper_bound(cnt1,cnt1+n,r)-1-cnt1;
else rr=n-1;
cout << r-l << " " << rr-ll+1 << endl;
for(int i=ll;i<=rr;i++) {
cout << cnt[i].y << " ";
}
cout << endl;
}else if(l<r) {
int rr;
int ll=lower_bound(cnt1,cnt1+n,l)-cnt1;
if((cnt[n-1].x)!=r) rr=upper_bound(cnt1,cnt1+n,r)-1-cnt1;
else rr=n-1;
cout << r-l << " " << rr-ll+1 << endl;
for(int i=ll;i<=rr;i++) {
cout << cnt[i].y << " ";
}
cout << endl;
}else {
int rr;
int ll=lower_bound(cnt1,cnt1+n,r)-cnt1;
int llr=upper_bound(cnt1,cnt1+n,r)-1-cnt1;
if((cnt[n-1].x)!=l)
{
rr=upper_bound(cnt1,cnt1+n,l)-1-cnt1;
}
else rr=n-1;
int rrl=lower_bound(cnt1,cnt1+n,l)-cnt1;
cout << abs(r-l) << " " << rr-ll+1 << endl;
for(int i=rrl;i<=rr;i++) {
cout << cnt[i].y << " ";
}
for(int i=rrl-1;i>llr;i--) {
cout << cnt[i].y << " ";
}
for(int i=ll;i<=llr;i++) {
cout << cnt[i].y << " ";
}
cout << endl;
}
}
}
d. Friends and the Restaurant
主要是要发现两个人情况永远比三个人好,其实很好证明。我用预算减去支出表示我的富有程度。如果是三个人++-的富有,那么我两个++富有程度的一定优于三个,同理--+的少去一个-也更优。所以最优就是两两一组找最优。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int A[N],B[N],cnt[N];
int main()
{
int t;
cin >> t;
while(t--) {
int n;
cin >> n;
for(int i=1;i<=n;i++) {
cin >> A[i];
}
for(int i=1;i<=n;i++) {
cin >> B[i];
cnt[i]=B[i]-A[i];
}
sort(cnt+1,cnt+1+n);
int l=1,r=n,sum=0;
while(l<r) {
if(cnt[l]+cnt[r]>=0) {
l++;
r--;
sum++;
}else {
l++;
}
}
cout << sum << endl;
}
}