哞叫时间Ⅱ

题目链接:https://www.acwing.com/problem/content/description/6137/

题意:

给定一个长度为n的数组,求出三个数ai,ap,aq(ai!=ap,ap=aq)(i<p<q)的种类数量

思路:

时间复杂度需O(n),因此程序只能有一重循环搞定
不妨从后向前遍历,如果一个数字出现次数==两次,让计数器k++。
由于我们需要种类不能重复,且要满足122式的条件。所以用res记录(i,n】的出现次数大于等于2的数字总数,用ai去配
那么不难发现,如果ai本身出现大于等于2次,需要将ai ai ai这种情况剔除一次,如果ai遍历过了,那么只需要看现在遍历的位置和ai上次出现位置之间,有哪些新的数出现次数大于等于2次加上去即可
可能表达的不是很清楚,希望代码更容易让人懂一些

#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define pb push_back
#define int long long
#define endl "\n"
#pragma GCC optimize(3)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int inf=0x3f3f3f3f;
const ll llmax=LLONG_MAX;
const int maxn=1e6+5;
const int mod=1e9+7;
int n;
int a[maxn];
int tot[maxn];
int ans;
int res[maxn];
int k;
bool vis[maxn];
pii pos[maxn];
signed main()
{
ios::sync_with_stdio(false),cin.tie(0);
cin>>n;
rep(i,1,n) cin>>a[i];
for(int i=n;i>=1;i--){
tot[a[i]]++;
res[i]=k;
if(tot[a[i]]==2){
k++;
}
if(i<=n-2){
if(!vis[a[i]]){
ans+=res[i];
if(tot[a[i]]>2&&pos[a[i]].second==0){
ans--;
pos[a[i]].second=1;
}
vis[a[i]]=true;
pos[a[i]].first=i;
}else{
ans+=(res[i]-res[pos[a[i]].first]);
if(tot[a[i]]>2&&pos[a[i]].second==0){
ans--;pos[a[i]].second=1;
}
pos[a[i]].first=i;
}
}
}
cout<<ans;
return 0;
}
posted @   Marinaco  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
//雪花飘落效果
点击右上角即可分享
微信分享提示