C
给出n,再给长度为n的一组小于等于n的数,问具有重复数的最小连续子串的长度是多少。
思路:有选择的排序。
#include <iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
//int a[200005];
struct node
{
int index;
int val;
}a[200005];
bool cmp(node p1,node p2)
{
if(p1.val==p2.val)
return p1.index<p2.index;
else return p1.val<p2.val;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].val);
a[i].index=i;
}
sort(a+1,a+1+n,cmp);
/* for(int i=1;i<=n;i++)
cout<<a[i].val<<" "<<a[i].index<<endl;*/
int ans=1e6+10;
for(int i=1;i<=n-1;i++)
{
if(a[i].val==a[i+1].val)
{
// cout<<tt<<endl;
ans=min(ans,a[i+1].index-a[i].index+1);
// cout<<ans<<endl;
}
}
if(ans<1e6) printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}
D
有n个怪物,m个英雄,每天可派出一个英雄去杀怪物,每个英雄每天最多杀ai个怪物,若遇到力量值大于英雄的怪物,英雄撤退,英雄可以无限次使用,问最少需要多少天杀光或者是不可能完成。
思路:由于可以无限次使用,那么,忍耐值大的留下,忍耐值相同,力量值大的留下。预处理出一个数组,专门存放力量值最大,忍耐值最好的英雄,然后定义两个指针,一个指向怪物,一个指向英雄,模拟情况。
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define ll long long
using namespace std;
const int N=2e5+5;
int a[N],b[N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1; i<=n; i++)
{
cin>>a[i];
}
int x,y;
int m;
for(int i=1;i<=n+4;i++)
b[i]=0;
cin>>m;
for(int i=1; i<=m; i++)
{
cin>>x>>y;
b[y]=max(x,b[y]);
}
for(int i=n; i>=1; i--)
{
b[i]=max(b[i],b[i+1]);
}
int cnt=0;
int pos1=1,pos2=1;
int tt=0;
bool flag=true;
while(1)
{
if(pos1>n) break;
cnt++;
tt=0;
while(1)
{
tt=max(tt,a[pos1]);
if(tt>b[pos2])
{
pos2=1;
break;
}
pos1++;
pos2++;
if(pos1>n) break;
}
if(pos1>n) break;
if(tt>b[1])
{
flag=false;
break;
}
}
if(flag)
{
cout<<cnt<<endl;
}
else cout<<"-1"<<endl;
}
return 0;
}
E
给出三堆数, 这三堆数由1-n组成,无重复数字,把其中一堆数的一个数给另一堆数花费为1,问要使第一堆是前缀,第三堆是后缀,第二堆是中间的最小花费是多少?这里可以使任何两堆数的个数为零。
思路:
第一感觉是dp应该能解决,但是,想不出来。
看网上一个巧妙的dp方法,设dp[i][k]表示第i个数分配完以后,若i分配给第k堆得最小花费。
dp[i][k]=min(d[i][k],dp[i-1][j]+1(如果当前这个数不在j堆得话))其中j要小于k.
文章链接:https://blog.csdn.net/weixin_43562213/article/details/103168350
F
给一组数,问是否存在一个数,使得这组数的每一个数亦或这个数后,得到的新的一组数的每一个数的二进制表示的1的个数相等。范围 2^30之内。
思路:看题解的意思是说把2^30拆成两个部分,2的15次方的情况记录下来,两个二的15次方就能拼成2的30次方的情况,通过查哈希表看是否能找到所包含的情况,然后输出。虽说这么说是行,但是题解里的位运算让人头痛,里面位运算的作用还没太搞清楚。