CF1712C的题解
对于
我们能很清楚一点,因为
那我们首先得先记录每一个数出现的最后一个位置 last[a[i]]
,以及最后一个不满足 find
。
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
last[a[i]]=i;
if(a[i-1]>a[i]) find=i;
}
if(n==1)
{
printf("0\n");
continue;
}
然后我们用
一开始,令 l=1,r=find-1
然后遍历该区间的数,如果其中有一个数最后出现的位置超过了该区间的右端点,那么我们枚举范围就要往后调。
l=1,r=find-1,tmp=0,flag=0;
while(!flag)
{
flag=1;
for(int i=l;i<=r;i++)
{
tmp=max(tmp,last[a[i]]);//找到最右边的数
if(tmp>r) flag=0;//如果超过右端点,则打上标记
}
if(!flag) l=r+1,r=tmp;//如果超过,则更新左右端点,准备下一次枚举
}
最后只需要扫一遍
for(int i=1;i<=r;i++)
if(!b[a[i]])
{
tot++;
b[a[i]]++;
}
#include<cstdio>
#include<cstring>
int t;
int n;
int a[100010];
int b[100010];
int last[100010];
bool flag;
int tot;
int find;
int tmp;
int l,r;
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
scanf("%d",&t);
while(t--)
{
memset(b,0,sizeof(b));
tot=find=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
last[a[i]]=i;
if(a[i-1]>a[i]) find=i;
}
if(n==1)
{
printf("0\n");
continue;
}
l=1,r=find-1,tmp=0,flag=0;
while(!flag)
{
flag=1;
for(int i=l;i<=r;i++)
{
tmp=max(tmp,last[a[i]]);
if(tmp>r) flag=0;
}
if(!flag) l=r,r=tmp;
}
for(int i=1;i<=r;i++)
if(!b[a[i]])
{
tot++;
b[a[i]]++;
}
printf("%d\n",tot);
}
return 0;
}
时间复杂度?
输入的时间复杂度显然为
综上,单次询问时间复杂度为
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构