昨晚状态不怎么好,虽然前两个题做的还挺快(主要是太水了),第三个题就卡住了,一直在想怎么用技巧解决,想了好半天也没想到技巧,后来想着就暴力试一下吧,结果第一遍暴力忘记了一个步骤,脑子里想的挺好结果上去就WA,好几次提交才过了,第四个题也是一直觉得思路没错,一直WA,然后眼睁睁看着比赛结束了,很难受,这场比赛一直在犯马虎。我记得以前做题基本都一遍过,最近不知道咋了,老是出错,很烦躁。昨晚立的flag也破了,掉了十来分,不过知道自己错在哪里了就好,慢慢长经验(佛系)
给你n个数,若某两个数绝对值之差小于1,则可以去除其中一个,问最终能否只剩一个数。水题,排序后看是否有绝对值之差大于1的两个数即可
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstdio>
#include<vector>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=200005;
typedef long long ll;
ll t,a[55],n,i,j,k,ans,cnt,Max,Min;
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
cin>>n;
for(i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
for(i=2;i<=n;i++)
{
if(a[i]-a[i-1]>1) break;
}
if(i==n+1)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
}
给你两组数a,b,两组数的个数均为n,现在要使两组数分别相等(a中全部相等且b中全部相等),每次可以让其中一个a-1或其中一个b-1或对应的二者都减一,问至少多少次能使两组数分别相等。水题,看每组中的最小值,直接相加二者与最小值的差中较大的那个值即可。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstdio>
#include<vector>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=55;
typedef long long ll;
ll t,a[maxn],b[maxn],n,i,j,k,ans,cnt,sum,Max,Min1,Min2,Min;
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
cin>>n;
Min1=INF;
Min2=INF;
sum=0;
for(i=1; i<=n; i++)
{
cin>>a[i];
Min1=min(Min1,a[i]);
}
for(i=1; i<=n; i++)
{
cin>>b[i];
Min2=min(Min2,b[i]);
}
for(i=1;i<=n;i++)
{
sum+=max(a[i]-Min1,b[i]-Min2);
}
cout<<sum<<endl;
}
}
n个人参加龙舟比赛,每两人组队,二者质量之和必须相等,问最多能组成多少队。我直接暴力过的,没啥说法了。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstdio>
#include<vector>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=55;
typedef long long ll;
ll t,a[maxn],b[2*maxn],w,n,i,j,k,ans,cnt,sum,index,Max,Min1,Min2,Min;
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
cin>>n;
for(i=1; i<=n; i++)
{
cin>>a[i];
}
sort(a+1,a+1+n);
Max=0;
for(i=1; i<=n; i++)
{
for(j=n; j>i; j--)
{
sum=0;
index=a[i]+a[j];
ans=j;
cnt=i;
while(cnt<ans)
{
if(a[cnt]+a[ans]==index)
{
sum++;
cnt++;
ans--;
}
else if(a[cnt]+a[ans]<index)
{
cnt++;
}
else if(a[cnt]+a[ans]>index)
{
ans--;
}
}
Max=max(Max,sum);
}
}
cout<<Max<<endl;
}
}
D. Binary String To Subsequences
给你一串二进制字符串,从中挑出最少的子串,使得子串的0和1均不相邻。问最少的子串数量是多少。我刚开始想的是只需要看连续的0或者1即可,找出最长连续的数字的长度,不连续的地方输出1,连续的地方就累加输出,后来发现假设输入00100,我代码的输出是12112,显然思路就不对了,答案应该是12223,至少需要三个子串。当时就这个地方没想透,然后一直WA。下面是代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstdio>
#include<vector>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=200005;
typedef long long ll;
int t,a[maxn],w,n,i,j,k,ans,cnt,sum,index,Max,Min1,Min2,Min;
char s[maxn];
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
k=0;
sum=0;
cin>>n;
cin>>s;
queue<int> q1,q0;
for(i=0;i<n;i++)
{
if(s[i]=='0')
{
if(q0.size()!=0)
{
int x=q0.front();
q0.pop();
a[i]=a[x];
q1.push(i);
}
else
{
a[i]=++sum;
q1.push(i);
}
}
else
{
if(q1.size()!=0)
{
int x=q1.front();
q1.pop();
a[i]=a[x];
q0.push(i);
}
else
{
a[i]=++sum;
q0.push(i);
}
}
}
cout<<sum<<endl;
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<endl;
}
return 0;
}
E1. Weights Division (easy version)
如果我没理解错的话,应该是一个无向连通图,每条边都有一个权值,路径的权值是该路径上边权值的总和。从顶点到自身的路径权值为0,每次移动,你都可以选择一条边并将其权值整除2。题目要求找出使从根到每个叶的路径的权值之和最多为S所需的最小移动次数。
E2. Weights Division (hard version)
与E1类似,但是所求的东西不同,E2要求求出最小权值和,使从根到每个叶的路径的权值之和最小。
F. Yet Another Segments Subset
给你n个线段的始末坐标,你需要从给出的线段集的选出最多的线段数组成其子集,子集要么每两个线段不相交,要么一个包含另一个。输出给定线段集的最大子集大小。