luogu P1966 火柴排队

做水题好爽...
展开式子
就是最大化\(2*a_i*b_i\)
显然令大的乘大的能最大化上式
相当于用最小步数把1序列转化为2序列
映射后求逆序对.

#include<cstdio>
#include<cstring>
#include<algorithm>

inline int read() {
    int x = 0,f = 1;
    char c = getchar();
    while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();}
    while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
    return x * f;
}

const int maxn  = 100007; 
#define lowbit(x) (x & (- x))
#define mod 99999997
int n ;
struct C {
    int v,id;
    C (int v = 0,int id = 0) : v(v),id(id) {};
    bool operator < (const C &a)const {
        return v < a.v;
    }
} a[maxn],b[maxn];
int has[maxn],tree[maxn << 2];
void update(int x) {for(;x <= n;tree[x] += 1,x += lowbit(x));}
int query(int x) {int ret = 0;for(;x >= 1;ret += tree[x],x -= lowbit(x));return ret;}
int main() {
    n = read();
    for(int i = 1;i <= n;++ i) a[i] = C(read(),i);
    for(int i = 1;i <= n;++ i) b[i] = C(read(),i);
    std::sort(a + 1,a + n + 1);
    std::sort(b + 1,b + n + 1);
    for(int i = 1;i <= n;++ i) has[a[i].id] = b[i].id;
    int ans = 0;
    for(int i = 1;i <= n;++ i) {
        update(has[i]);
        ans =(ans + i - query(has[i])) % mod; 
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/sssy/p/8969519.html