[ABC261F] Sorting Color Balls

前言

本题中大多数人都是用的逆序对,这里提供一种不需要逆序对的方法。

思路

我们可以发现,我们可以从 \(a\sim Max\) 去移动没一个数,这里的 \(Max\) 是指 \(x\) 的最大值,然后我们可以通过排序得出对于 \(x\)\(i\) 的应该出现在 \(l\sim r\) 这个区间,那么我们通过手玩可以发现我们对于每一个 \(i\) 可以将第一个 \(x\) 移到 \(l\) 将第 \(2\) 个移动到 \(l+1\) 的位置,然后以此类推。

那么我们,就可以得出一个公式就是对于一个 \(i\) 的贡献为 \(wei_i+small_i-now-same_i\) 这里我们的 \(wei_i\) 为第 \(i\) 个数在原数组中出现的位置,\(small_i\) 为原数组中在 \(i\) 之后且 \(x\) 小于 \(i\)\(x\) 的数量,然后 \(now\) 为当前的目标点,最后 \(same_i\) 为在 \(i\) 之前且 \(c\) 等于 \(i\)\(c\) 并且 \(x\) 大于 \(i\)\(x\) 的数量。

这样做为什么是对的呢?因为我们是从小到大来移动的 \(x\) 所以我们对于所有 \(x\) 小于 \(i\)\(x\) 且在其后面的都会经过 \(i\) 那么每经过一次就会把 \(i\) 往后移动一个位置,然后我们将 \(x\) 小于 \(i.x\) 的移动完之后 \(i\) 的位置就是 \(wei_i+small_i\)

然后通过左右区间可以算出需要的步数(这里先忽略 \(c\))然后我们对于能抵消的必须是在 \(i\) 前面且 \(c\) 要和其相等的还有 \(x\) 要大于 \(i.x\) 的,那么我们可以用两个树状数组,一个求解 \(small_i\) 一个求解 \(same_i\) 即可。

代码

#include <bits/stdc++.h>
using namespace std ;
#define int long long
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define rep1(i,x,y) for(int i=x;i>=y;i--)
#define fire signed
#define kong putchar(' ')
#define end putchar('\n')
#define in(x) scanf("%lld",&x)
#define lcm(x,y) x*y/__gcd(x,y)
#define w(x)  while(x--)
#define il inline
il void print(int x) {
	if(x>=10) print(x/10);
	putchar(x%10+'0');
}
int n;
const int N=3e5+10;
struct node {
	int c,x,id;
} s[N];
bool cmp(node a,node b) {
	if(a.x!=b.x) return a.x<b.x;
	return a.id>b.id;
}
vector<int>v[N];
vector<pair<int,int>>ve[N];
int cnt[N];
int small[N];
int shao[N];
int now[N],shor[N];
int res;
struct Node {
	int l,r;
} a[N];
int tr[N];
int lowbit(int x) {
	return x&(- x);
}
void add(int x,int k) {
	for(; x<=n; x+=lowbit(x)) tr[x]+=k;
}
int Ans(int x) {
	int res=false;
	for(; x; x-=lowbit(x)) {
		res+=tr[x];
	}
	return res;
}
set<int>se;
fire main() {
	in(n);
	rep(i,1,n) in(s[i].c),s[i].id=i;
	rep(i,1,n) in(s[i].x),cnt[s[i].x]++,se.insert(s[i].c);
	rep(i,1,n) v[s[i].x].push_back(i);
	rep(i,1,n) ve[s[i].c].push_back({s[i].x,i});
	rep1(i,n,1) {
		small[i]=Ans(s[i].x-1);
		add(s[i].x,1);
	}
	rep(i,1,n) tr[i]=0;
//	add(2,1);
//	add(2,-1);
//	rep(i,1,n) cout<<tr[i]<<" ";
	for(auto i:se) {
		for(pair<int,int> x:ve[i]) {
			shao[x.second]=Ans(x.first);
			add(x.first,1);
		}
//		cout<<endl;
		for(pair<int,int> x:ve[i]) add(x.first,-1);
//		cout<<endl;
	}
	rep(i,1,n) {
		shor[i]=now[s[i].c]-shao[i];
		now[s[i].c]++;
	}
	sort(s+1,s+1+n,cmp);
	rep(i,1,n) {
		if(!a[s[i].x].l) a[s[i].x].l=i;
		a[s[i].x].r=i;
	}
	rep(i,1,n) {
		if(!cnt[i]) continue;
		int now=a[i].l;
		for(auto x:v[i]) {
			res+=((x+small[x])-now)-shor[x];
			now++;
		}
	}
	print(res);
	return false;
}
posted @ 2024-01-31 11:43  highkj  阅读(7)  评论(0)    收藏  举报