题解:[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;
}
posted @ 2026-06-29 13:51  TH911  阅读(0)  评论(0)    收藏  举报