哞叫时间Ⅱ
题目链接: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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现