AtCoder Beginner Contest 261 F

F - Sorting Color Balls

我们不难发现排序的花费一定是逆序对的数量 并且 颜色相同的逆序对也不会耗费
那我们求一次总的逆序对 再颜色相同都求一次逆序对即可
但是注意每次求完都要清空 我们可以直接add(x,-1)即可

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5+10;
const int M = 998244353;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define all(x) (x).begin(),(x).end()
#define YES cout<<"Yes"<<endl;
#define NO cout<<"No"<<endl;
#define _ 0
#define INF 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int a[N],d[N],t[N],n,c[N];
vector<int>v[N];
bool cmp(int x,int y){
    if(a[x]==a[y])return x<y;
    return a[x]<a[y];
}//按a的大小将d排序
int lowbit(int x){
    return x&(-x);
}
void add(int x,int c){
    while(x<=n){
        t[x]+=c;
        x+= lowbit(x);
    }
}
int getsum(int x){
    int res=0;
    while(x){//x>=1也可以反正0没动过
        res+=t[x];
        x-= lowbit(x);
    }
    return res;
}
void solve() {
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>c[i];
        v[c[i]].push_back(i);
    }
    for(int i=1;i<=n;i++){
        cin>>a[i];
        d[i]=i;
    }
    sort(d+1,d+n+1,cmp);
    int ans=0;
    for(int i=1;i<=n;i++){
        add(d[i],1);//将d[i]插进去
        ans+=i-getsum(d[i]);//求小于d[i]的个数
    }
    for(int i=1;i<=n;i++)add(d[i],-1);
    for(int i=1;i<=n;i++){
        int res=0;
        sort(all(v[i]),cmp);
        int cnt=1;
        for(auto j:v[i]){
            add(j,1);
            res+=cnt-getsum(j);
            cnt++;
        }
        for(auto j:v[i]){
            add(j,-1);
        }
        ans-=res;
    }
    cout<<ans<<endl;
}
signed main(){
    fast
    int T;T=1;
    while(T--) {
        solve();
    }
    return ~~(0^_^0);
}
posted @ 2022-09-16 18:59  ycllz  阅读(30)  评论(0)    收藏  举报