A.
题意:一共n个点,有俩点叫a b,可以进行m次交换操作,问最大ab点相距多少。
水题
#include<iostream>
#include<cmath>
using namespace std;
int min(int a,int b){
return a<b?a:b;
}
int main(){
int t;
int n,m,a,b;
cin>>t;
while(t--)
{
cin>>n>>m>>a>>b;
int dis=abs(a-b);
int ans=min(dis+m,n-1);
cout<<ans<<endl;
}
}
B做过了
C.
题意:给n个数,求这之中两个相同的数字最小距离是多少
思路:题意挺简单的,但是理解题意的时候可费劲了,他叙述的跟多复杂一样,什么dominated by,根本就看不懂,明明就是这点事,英语还是要好好学,一开始的做法还挺复杂的,就是想着一点点处理,但是wa了,看不出来哪里错了,然后改了个思路,用一个vis数组表示每个数是否输入过并且表示他最后一次出现的位置,每次输入的时候,如果之前没有输入过,就把vis设为当前的位置,输入过就求距离比较,找到最小的。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
typedef long int ll;
int a[200005],vis[200005];
int main()
{
int t;
int n,i,j;
cin>>t;
while(t--)
{
memset(vis,0,sizeof(vis));
cin>>n;
int ans=inf;
int flag=0;
for(i=1;i<=n;i++)
{
cin>>a[i];
if(vis[a[i]]==0) vis[a[i]]=i;
else{
flag=1;
if(abs(vis[a[i]]-i)<ans) ans=abs(vis[a[i]]-i);
vis[a[i]]=i;
}
}
if(flag)
cout<<ans+1<<endl;
else
cout<<-1<<endl;
}
return 0;
}
D.
题意:有丶复杂,你有m个英雄,每个英雄有力量值和耐力值,然后按顺序要打n个怪兽,每个怪兽也有力量值,如果英雄的力量值大于等于怪兽就可以干掉他,在一天中会消耗掉他的一个耐力值,问你最少可以用多少天来弄死所有怪兽。
思路:自己想的时候忽略了一个点,就是每个英雄不只可以用一次,因为他在战斗后休息一天,耐力值会回复满,这点错了,导致思路有点乱,按每个英雄处理,看每个英雄应该放在什么地方最好,但是会涉及很多问题,太复杂了。比赛的时候时间也不是很多了就没有继续往下做,看到了别人的题解之后就又懂了。用简单的贪心就能做,用一个数组suf[i]表示,耐力值大于等于i的英雄最大的力量是多少。然后从左向右对怪兽进行直接处理,有了一个suf数组就可以直接处理了,贪心思想就是在每个地方能用的英雄的最大耐力是多少,用一个maxx表示接下来要面对的怪兽力量是多少。这样一看,这思路挺简单的。
#include<iostream>
using namespace std;
const int maxn=2e5+10;
int n,m;
int a[maxn];
int suf[maxn],b[maxn];
int p[maxn],s[maxn];
int main()
{
int t,i,j;
cin>>t;
while(t--){
cin>>n;
for(i=1;i<=n;i++) b[i]=-1;
for(i=1;i<=n;i++) cin>>a[i];
cin>>m;
for(i=1;i<=m;i++) {
cin>>s[i]>>p[i];
if(b[s[i]]<p[i]) b[s[i]]=p[i];
}
suf[n+1]=-1;
for(i=n;i>0;i--) suf[i]=max(suf[i+1],b[i]);
int pis=1,ans=0;
while(pis<=n)
{
int cnt=pis;
int maxx=a[pis];
while(cnt<=n&&suf[cnt-pis+1]>=maxx){
cnt++;
maxx=max(maxx,a[cnt]);
}
if(cnt==pis){ans=-1;break;}
ans++;
pis=cnt;
}
cout<<ans<<endl;
}
}
E.
题意:三个人,每个人掌握着几个数,三人一共掌握1到n n个数,问你怎样怎样用最小的操作数达到,三人分别掌握1到i,i+1到j,j+1到n几个数。
思路:处理前缀和,用cnt数组分别表示三人前i个数中有几个数,具体的推导还是看的别人作得。
#include <bits/stdc++.h>
#define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define LL long long
using namespace std;
const int maxn = (ll) 2e5 + 5;
const int mod = 1000000007;
const int inf = 0x3f3f3f3f;
int cnt1[maxn], cnt2[maxn], cnt3[maxn];
int minn[maxn];
vector<int> v1, v2, v3;
int main() {
start;
int k1, k2, k3;
cin >> k1 >> k2 >> k3;
v1.resize(k1 + 5);
v2.resize(k2 + 5);
v3.resize(k3 + 5);
for (int i = 1; i <= k1; ++i) {
cin >> v1[i];
++cnt1[v1[i]];
}
for (int i = 1; i <= k2; ++i) {
cin >> v2[i];
++cnt2[v2[i]];
}
for (int i = 1; i <= k3; ++i) {
cin >> v3[i];
++cnt3[v3[i]];
}
int n = k1 + k2 + k3;
for (int i = 1; i <= n; ++i) {
cnt1[i] = cnt1[i - 1] + cnt1[i];
cnt2[i] = cnt2[i - 1] + cnt2[i];
cnt3[i] = cnt3[i - 1] + cnt3[i];
}
for (int i = 0; i <= n; ++i)
minn[i] = cnt3[i] - cnt2[i];
for (int i = n - 1; i >= 0; --i)
minn[i] = min(minn[i + 1], minn[i]);
int ans = inf;
for (int i = 0; i <= n; ++i) {
int t = cnt2[i] - cnt1[i] + minn[i] + cnt1[n] + cnt2[n];
ans = min(ans, t);
}
cout << ans;
return 0;
}
F.
题意:给n个数,每个数给用一个x异或操作,让他们最后得到的二进制数1的个数相同,问这个数是多少。
思路:我见过这题,我记得是c题,当时补题的时候就没看懂,没想到这么快就遇到了,该学的还是要早点学啊,相似度这么高的题都做不出来确实是不应该。
#include <bits/stdc++.h>
#define LL long long
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f3f
#define mem(i, j) memset(i, j, sizeof(i))
#define pb push_back
using namespace std;
int ans = -1, n;
map < vector< int >, int > mp;
vector< int > Q;
int a[105];
void dfs1(int num, int statu){
if(num > 15) {
Q.clear();
for(int i = 1; i <= n; i++) {
Q.push_back(__builtin_popcount((statu ^ a[i]) % (1 << 15)));
}
for(int i = 1; i < n; i++) {
Q[i - 1] = Q[i] - Q[i - 1];
}
Q.pop_back();
if(!mp[Q]) mp[Q] = statu;
return ;
}
dfs1(num + 1, statu);
dfs1(num + 1, statu | (1 << (num - 1)));
}
void dfs2(int num, int statu) {
if(num > 15) {
Q.clear();
for(int i = 1; i <= n; i++){
///__builtin_popcount(x) 用于计算x的二进制位上1的个数。
Q.push_back(__builtin_popcount(statu ^ (a[i] >> 15)));
}
for(int i = 1; i < n; i++) {
Q[i - 1] = -1 * (Q[i] - Q[i - 1]);
}
Q.pop_back(); /// 弹出最后一个元素。
if(mp[Q]) {
ans = mp[Q] | (statu << 15);
}
return ;
}
dfs2(num + 1, statu);
dfs2(num + 1, statu | (1 << (num - 1)));
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
dfs1(1, 0); dfs2(1, 0);
printf("%d\n", ans);
return 0;
}