A
思路
选一个移动步即可,注意距离最大为的限制。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
puts("");
}
void solve()
{
ll n,x,a,b;
In(4,&n,&x,&a,&b);
if(a>b)
swap(a,b);
ll ans=min(n-1ll,b-(a-x));
Out(1,ans);
}
int main()
{
int _;
cin>>_;
while(_--)
{
solve();
}
}
B
思路
第一种操作可以使当前数字变大,第二种操作是变小,因为第二种操作每次都减,因此只要得到一个比大的数字就一定可以得到。观察发现当最小为时可以通过操作得到一个无限大的数,因此只需要特判时的情况即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
puts("");
}
void solve()
{
ll x,y,cnt=0;
In(2,&x,&y);
if(x>=4)
puts("YES");
else if(x==1 && y>1)
puts("NO");
else if(x==2 && y>3)
puts("NO");
else if(x==3 && y>3)
puts("NO");
else
puts("YES");
}
int main()
{
int _;
cin>>_;
while(_--)
{
solve();
}
}
C
思路
最终得到的序列必定有且只有一个元素出现过两次,其他元素仅出现一次,维护相同元素的最近距离即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
puts("");
}
const int N=2E5+10;
ll vis[N];
void solve()
{
ll n;
In(1,&n);
rep(i,1,n)
vis[i]=0;
ll x;
ll ans=LLM;
rep(i,1,n)
{
In(1,&x);
if(vis[x])
ans=min(ans,i-vis[x]+1);
vis[x]=i;
}
if(ans==LLM)
ans=-1;
Out(1,ans);
}
int main()
{
int _;
cin>>_;
while(_--)
{
solve();
}
}
D
思路
考虑两个耐力相同的英雄,肯定是留下能力最强的一个。每次打怪都尽可能多地打,因为如果这一天有一只怪本来能打却没有打,那么它不仅会消耗第二天英雄的耐力,还有可能卡住能力上限使我们不能挑耐力好一点但是能力低的英雄获得更优解。
考虑一天最多能打几只。如果只打一只,我们可以从所有耐力值不小于的英雄中选一个能力值足够的来打,如果继续打第二只,就需要存在一个英雄耐力值不小于且能力值足够。我们发现如果一天要打只怪,就需要所有耐力值不小于的英雄能力值至少为这些怪物的最大值。
因此设为耐力至少为的英雄的最大能力值,然后模拟打怪过程,每天枚举的下标(即今天打多少只怪),看对应的值是否满足能力值要求。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
const int N=2E5+10;
ll n,m;
ll a[N],f[N];
void print()
{
rep(i,1,n)
Out_(1,f[i]);
puts("");
}
void solve()
{
ll ans=0;
In(1,&n);
rep(i,1,n)
{
f[i]=0;
In(1,&a[i]);
}
In(1,&m);
rep(i,1,m)
{
ll p,s;
In(2,&p,&s);
f[s]=max(f[s],p);
}
for(int i=n-1;i>=1;--i)
f[i]=max(f[i],f[i+1]);
ll cur=1;
f[0]=f[1];
while(cur<=n)
{
ll end=cur;
ll maxi=0;
while(end<=n && f[end-cur+1]>=a[end] && f[end-cur+1]>=maxi)
{
maxi=max(maxi,a[end]);
++end;
}
--end;
if(end<cur)
{
ans=-1;
break;
}
++ans;
cur=end+1;
}
Out(1,ans);
}
int main()
{
int _;
cin>>_;
while(_--)
{
solve();
}
}
E
思路
从只有两个人的情况找规律,然后拓展到三个人。这条博客讲得很详细。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
const int N=2E5+10;
ll k1,k2,k3,n;
ll cnt1[N],cnt2[N],cnt3[N],mini[N];
int main()
{
In(3,&k1,&k2,&k3);
n=k1+k2+k3;
rep(i,1,k1)
{
ll tmp;
In(1,&tmp);
++cnt1[tmp];
}
rep(i,1,k2)
{
ll tmp;
In(1,&tmp);
++cnt2[tmp];
}
rep(i,1,k3)
{
ll tmp;
In(1,&tmp);
++cnt3[tmp];
}
rep(i,1,n)
{
cnt1[i]+=cnt1[i-1];
cnt2[i]+=cnt2[i-1];
cnt3[i]+=cnt3[i-1];
}
mini[n+1]=LLM;
for(int i=n;i>=0;--i)
{
mini[i]=min(mini[i+1],cnt3[i]-cnt2[i]);
}
ll ans=LLM;
rep(i,0,n)
{
ans=min(ans,cnt2[i]-cnt1[i]+mini[i]);
}
ans+=cnt1[n]+cnt2[n];
Out(1,ans);
}
F
思路
枚举必然超时,考虑如何优化。两个数字的数目相同,必有这两个数字前位的数目之差与后位的数目之差互为相反数。考虑以为基准,只要所有数字的数目都和相同,那么所有数字的数目就都相同了。因此分别枚举答案的前位和后位,将前位异或后得到的存在中,用维护某个是否出现过。只要在枚举后位时出现了一个恰好符号相反的(其实只需要把式子换成并在中查询),就说明找到了答案,将前位和后位拼起来即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
ll ct(ll o)
{
register ll ret=0,x=o,t;
while(x)
{
t=x&-x;
x-=t;
++ret;
}
return ret;
}
const ll N=105;
ll n;
ll l[N],h[N],cnt[(1<<15)+10];
map<vector<ll>,ll> ma;
int main()
{
In(1,&n);
rep(i,1,n)
{
ll tmp;
In(1,&tmp);
l[i]=tmp&((1<<15)-1);
h[i]=tmp>>15;
}
ll lim=(1<<15)-1;
rep(i,0,lim)
{
ll v=i;
while(v)
{
if(v&1)
++cnt[i];
v>>=1;
}
}
rep(x,0,lim)
{
vector<ll> tmp;
tmp.clear();
ll fir=cnt[l[1]^x];
rep(i,2,n)
{
tmp.push_back(fir-cnt[l[i]^x]);
}
ma.insert(ma.end(),make_pair(tmp,x));
}
rep(x,0,lim)
{
vector<ll> tmp;
tmp.clear();
ll fir=cnt[h[1]^x];
rep(i,2,n)
{
tmp.push_back(cnt[h[i]^x]-fir);
}
if(ma.find(tmp)!=ma.end())
{
Out(1,(x<<15)+ma[tmp]);
return 0;
}
}
Out(1,-1ll);
}