第一题签到题就不讲了【只要是个人就会好吧】
然后是第二题,这个题是一个最长连续子序列的一个扩展题,只不过是条件不同了罢了;
先看题:
所以我们用的是双指针算法跟哈希表;
因为每个数字的范围都很小,所以不用特地写哈希表,直接一个数组就可以了,即ha[i]存储i这个数字在当前范围内出现的次数;
定义一个变量qua,存储当前范围内不同数的个数
然后我们的指针i、j从1开始,进行以下循环:
(1)j指向数字A
~如果ha[A]==0,那么qua++,ha[A]++;
~ha[A]!=0,那么只要ha[A]++;
(2)如果qua>k
1:ha[i]--;
~:如果ha[i]==0,那么que--,i++
~:否则只i++
那么下面是具体代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int N=500010;
int ha[N];
int st[N];
int n,k;
int qua;
int l,r;
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++) scanf("%d",&st[i]);
for(int i=1,j=1;j<=n;j++){
if(ha[st[j]]!=0) ha[st[j]]++;
else ha[st[j]]++,qua++;
while(qua>k){
ha[st[i]]--;
if(!ha[st[i]]) qua--;
i++;
}
if(r-l+1<=j-i+1) r=j,l=i;
}
cout<<l<<' '<<r;
}
那么是下一道......题
我们先抽象一下我们要干的事情:
其实就在a、b数组找一段连续区间,然后对两个区间分别求和,如何相乘,得到的结果小于x,在这种区间之间,我们要找到两段长度相乘最大的那个;
那么我们要怎么写呢?
这里我们要用到单调栈的思想:
要明确一个结论:长度相同的区间,和越小越好;
领悟了这句话,那么就可以用o(n^2)的时间复杂度算出来了:
我们对两个数组进行处理,最后得到两个组数据:
a1[i]存储着长度为i的区间和最小值,b1[i]同理;
然后我们a1、b1数组进行遍历寻找答案;
下面是代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int N=2010;
ll oa[N],ob[N];
ll a[N],b[N];
ll fixa[N],fixb[N];
ll n,m,x;
ll ans;
int main(){
cin>>n>>m;
memset(oa,0x3f,sizeof oa); memset(ob,0x3f,sizeof ob);
for(int i=1;i<=n;i++) cin>>a[i],fixa[i]=fixa[i-1]+a[i];
for(int i=1;i<=m;i++) cin>>b[i],fixb[i]=fixb[i-1]+b[i];
cin>>x;
for(int len=1;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
int j=i+len-1;
ll sum=fixa[j]-fixa[i-1];
oa[len]=min(oa[len],sum);
}
}
for(int len=1;len<=m;len++){
for(int i=1;i+len-1<=m;i++){
int j=i+len-1;
ll sum=fixb[j]-fixb[i-1];
ob[len]=min(ob[len],sum);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(oa[i]*ob[j]<=x) ans=max((ll)i*j,ans);
}
}
cout<<ans;
}