题解:[ABC452F] Interval Inversion Count
题意分析
考虑逆序对数量恰好等于 \(k\) 的不好求,可以求逆序对数量大于等于 \(k\) 的区间数 \(\operatorname{calc}(k)\),答案即 \(\operatorname{calc}(k)-\operatorname{calc}(k+1)\)。
容易发现对于区间 \([l,r]\),\(l\) 固定的时候逆序对数量一定是随着 \(r\) 的增加而单调不降的。
因此如果 \([l,r]\) 的逆序对数量大于等于 \(k\),一定有 \([l,r+1],[l,r+2],\cdots,[l,n]\) 都是满足条件的,也就是说 \([l,r]\) 对于答案的贡献为 \(n-r+1\)。
因此双指针扫一遍,扫的时候用树状数组维护,判断逆序对的数量即可。
AC 代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
#include<set>
using namespace std;
typedef long long ll;
constexpr const int N=5e5;
int n,a[N+1];
struct bit{
int t[N+1+1];
int lowbit(int x){
return x&-x;
}
void add1(int x,int k){
while(x){
t[x]+=k;
x-=lowbit(x);
}
}
int query1(int x){
int ans=0;
while(x<=N+1){
ans+=t[x];
x+=lowbit(x);
}
return ans;
}
void add2(int x,int k){
while(x<=N+1){
t[x]+=k;
x+=lowbit(x);
}
}
int query2(int x){
if(x==0){
return 0;
}
int ans=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
void clear(){
memset(t,0,sizeof(t));
}
}t1,t2;
ll calc(ll k){
t1.clear();
t2.clear();
t1.add1(a[1],1);
t2.add2(a[1],1);
ll ans=0,cnt=0;
for(int l=1,r=1;l<=n;){
if(cnt<k&&r==n){
break;
}
if(cnt<k){
r++;
cnt+=t1.query1(a[r]+1);
t1.add1(a[r],1);
t2.add2(a[r],1);
}else{
ans+=n-r+1;
cnt-=t2.query2(a[l]-1);
t1.add1(a[l],-1);
t2.add2(a[l],-1);
l++;
r=max(l,r);
}
}
return ans;
}
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
ll k;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
cout<<calc(k)-calc(k+1)<<'\n';
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}

浙公网安备 33010602011771号