知识点模块
1.初始化一个有30位个1的二进制位
int a=(1<<30)-1
B. AND Sorting
这题我们发现将样例中的每个位置不匹配的按顺序与下去,得到的就是结果,猜一猜写一下,学习一下使用二进制数1111111111.....的初始化
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve()
{
int n;
cin>>n;
int ans= (1<<30) -1;//初始化一个很长的111111111
//其实他们的解释我也听不懂
//但是反正每个位置不同的数与一下就是样例的结果
//猜着猜着来吧
for(int i=0;i<n;i++)
{
int x;
cin>>x;
if(x!=i) ans&=x;
}
cout<<ans<<endl;
}
signed main()
{
int t=1;
cin>>t;
while(t--) solve();
return 0;
}
C. 3SUM Closure
1.假如有n个数,里面至少有3个数a>b>c>0,那么a+b+c>a是肯定的,这个元素肯定不符合题意,那么三个负数也是同理的。
2.我们注意到当三个数为0 0 x的时候,无论你的x是任何数,都是符合题意的,那么如果有很多个0和x,只需要取1个0,怎么理解呢,如果我们是-2,2,0,0其实和-2 2 0是等价的,举其他例子也是同理。
3.综上,我们其实最多只能取到两个正数,两个负数和一个0的情况,为什么一定要有1个0呢?因为我举不出来没有0可以符合的情况。
所以我们只需要检查一下,有没有0,检查一下有几个正数负数,检查完以后再暴力遍历验证一下就可以
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve()
{
int n,markz=0,markf=0,zero=0,check=1;
cin>>n;
vector<int>ve;
map<int,int>mp;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
if(x>0) {
if(++markz<3) ve.push_back(x),mp[x]=1,check=0;
}
else if(x<0)
{
if(++markf<3) ve.push_back(x),mp[x]=1,check=0;
}
else if(++zero==1) ve.push_back(x),mp[x]=1;
}
//如果有三个及以上正数或者三个及以上负数都不符合
//因为a+b+c>a(a最大) 负数同理
//由于0 0 x当x取任何数都符合情况,所以当有多个0的时候,我们只需要把一个放入数组即可
if(markz>=3||markf>=3) {
cout<<"NO"<<endl;
return ;
}
if(check==1) {
cout<<"YES"<<endl;
return;
}
for(int i=0;i<ve.size();i++)
{
for(int j=i+1;j<ve.size();j++)
{
for(int k=j+1;k<ve.size();k++)
{
if(mp[ve[i]+ve[j]+ve[k]]==0) {
cout<<"NO"<<endl;
return;
}
}
}
}
cout<<"YES"<<endl;
}
signed main()
{
int t=1;
cin>>t;
while(t--) solve();
return 0;
}
B. Different String
这一题只要检查一下是否全部为一个字母即可,如果有不同的字母,我们就把第一个和从0开始的第一个字母不同的字母标记一下,然后从标记处开始输出再输出0到标记处实现交换,当然可以参考官方的解答,遇到不同的两两交换也是行的
1.我自己的代码
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve()
{
string s;
cin>>s;
int pos=0,flag=0,cnt=0;
map<char,int>mp;
for(int i=0;i<s.size();i++)
{
if(mp[s[i]]==0){
cnt++;
mp[s[i]]++;
}
if(s[i]!=s[0]&&flag==0)
{
pos=i;
flag=1;
}
}
if(cnt==1) cout<<"NO"<<endl;
else {
cout<<"YES"<<endl;
for(int i=pos;i<s.size();i++) cout<<s[i];
for(int i=0;i<pos;i++) cout<<s[i];
cout<<endl;
}
}
signed main()
{
int t=1;
cin>>t;
while(t--) solve();
return 0;
}
C. Clock and Strings
这题的思路是化曲为直,其实我们可以想象一下,把圆从12处拉开成一条直线,那么如果两条直线相交则一定区间一定会有重叠的部分,那么不相交的只有包含关系和两者没有重叠部分的关系,所以只需要取一下两点的最大最小值讨论一下即可
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve()
{
int a,b,c,d;
cin>>a>>b>>c>>d;
int max1=max(a,b),max2=max(c,d),min1=min(a,b),min2=min(c,d);
if(min1>min2&&max1<max2||min2>min1&&max2<max1) cout<<"no"<<endl;
else if(max1<min2||max2<min1) cout<<"no"<<endl;
else cout<<"yes"<<endl;
}
signed main()
{
int t=1;
cin>>t;
while(t--) solve();
return 0;
}
D. Binary Cut
1.想要把序列弄成由0到1的有序排列,我们一定要有01这种连接的部分,而且只需要一个这种连接的部分即可,当然它可以是00001,001,000001等等
2.当我们从左往右遍历字符串的时候,我们只要遇到一个与上一个字符不同的,便是一个数据块(只有0和只有1的数字块),那么答案就是数据块的数量,再看有无01类似这样的连接块,有的话就是数据块-1,没有就是数据块的数量
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve()
{
string s;
cin>>s;
int res=0;
bool check=0;
for(int i=0;i<s.size();i++)
{
res+=(s[i]!=s[i+1]);
if(s[i]=='0'&&s[i+1]=='1') check=1;
}
cout<<res-check<<endl;
}
signed main()
{
int t=1;
cin>>t;
while(t--) solve();
return 0;
}
E. Find the Car
1.因为给出的每个已知点间的每一段速度是固定的,所以我们的思路就是先二分出第一个大于等于该查询值的路程下标,然后该下标-1,便是第一个小于该路程值已知点的下标,答案便是已知的花费时间+该段的差值/该段的固定速度,可以直接开int就能过