[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;
}

浙公网安备 33010602011771号