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