D2. Seating Arrangements (hard version)

每个人有视力ai和编号,编号就是进场顺序,然后分配座位si,

首先要保证视力小的人,座位一定要小于视力大的人

然后同一排,先坐下的人会挡住后面进场且路过他的人,此时记录贡献

求排好后,最小的贡献

 

首先视力小就得坐前面,所以可以首先按ai排序,那么这些相同视力的人可能会做若干排

1OOOOXX

2XXXXXXX

3XXZZZZZ

对于ai == X 的人内部,1排调整好进场顺序,就不计贡献,2排也是

对于3排来说,可能会挡住Z的进场,所以坐到3排的 ai == X 的人 编号必须大,进场顺序放后面

第一次排序按ai分好,相同ai的人编号大的要靠后,这样可以少Z的挡路

第二次排序对于同一排的人,首先要让ai分好,ai分好的情况下,相同ai的人编号大靠前,少挡住自己人X的路

O(nmm)

int n,m,maxx,c[N];
struct node{
    int pos,a;
}man[N];
int cmp(node x,node y){
    if (x.a == y.a)
        return x.pos < y.pos;
    return x.a < y.a;
}
int cmp2(node x,node y){
    if (x.a == y.a)
        return x.pos > y.pos;
    return x.a < y.a;
}
void solve(){
    scanf("%lld%lld",&n,&m);
    maxx = n * m;
    for(int i = 0 ; i < maxx ; ++ i){
        scanf("%lld",&man[i].a);
        man[i].pos = i ;
    }
    int ans = 0 ;
    sort(man, man + maxx,cmp);
    for(int i = 0 ; i < n; ++ i){
        int l = m * i ;
        int r = m * (i + 1);
        sort(man + l,man + r,cmp2);
        for(int j = l ; j < r ; ++ j){
            for(int k = j + 1 ; k < r ;++ k){
                if(man[k].a == man[j].a)continue;
                if(man[k].pos > man[j].pos)    ans++;
            }
        }
    }
    printf("%lld\n",ans);
}

 

posted @ 2021-09-22 20:09  PdrEam  阅读(63)  评论(0编辑  收藏  举报