feat: 添加P3660题解实现,使用树状数组计算交叉对数

实现了一个使用树状数组的解法来计算数组中成对元素的交叉对数。通过维护一个访问标记数组和树状数组来高效统计区间和,优化了计算过程。
This commit is contained in:
Zengtudor 2025-09-03 17:27:32 +08:00
parent 8aca422b9d
commit cc3380434c

55
src/9/3/P3660.cpp Normal file
View File

@ -0,0 +1,55 @@
#include <cstdint>
#include <iostream>
#include <istream>
#include <vector>
using ll = int64_t;
ll n,ans=0;
std::vector<ll> vis,t,a;
static inline ll lb(const ll n){
return n&(-n);
}
static inline void upd(ll idx,ll add){
while(idx<=2*n){ // 注意要*2
t[idx]+=add;
idx+=lb(idx);
}
}
static inline ll get(ll idx){
ll res=0;
while(idx){
res+=t[idx];
idx-=lb(idx);
}
return res;
}
int main(){
std::iostream::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin>>n;
a.resize(n*2+1);
vis.resize(n+1);
t.resize(n*2+1);
for(ll i=1;i<=n*2;i++){
std::cin>>a[i];
}
for(ll i=1;i<=n*2;i++){
if(vis[a[i]]){
ll nans=get(i)-get(vis[a[i]]);
ans+=nans;
// printf("%lld += %lld\n",i,nans);
upd(vis[a[i]], -1);
}else{
upd(i, 1);
vis[a[i]]=i;
}
}
std::cout<<ans<<"\n";
}