Test instructions: Give two permutations, find out the rank of each arrangement in the whole arrangement, add, modulo n! (the total number of rows) to obtain a number k, the arrangement of the row behavior K.
Solution: First of all to obtain a positioning method, that is, know that an arrangement is the first permutation. For example (0, 1, 2), (0, 2, 1 ), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0).
Take the Arrangement (1,2,0), the first is 1, the front has cnt=1 less than 1 of the unused number (0), so its ranking to add (cnt=1) *2!, the second is 2, because 1 has been put, so less than 2 is only 0, that is, cnt=1, so, the ranking also added (cnt=1) *1!, so the rank is 3.
Introduction of general Conclusions:
Pre[i] Represents the number of numbers that are less than I and are not occupied. We can use a tree-like array to update one side of the query to find out the two permutations of all pre[] values, save to the P array: p1[i] = pre1[b1[i]],p2[i] = Pre2[b2[i]]
Then rank and for (P1[i]+p2[i]) * (n-1)! + ... + (P1[n]+p2[n]) *0! = p3[1]* (n-1)! + ... + p3[n]*0! , but the resulting expression may not be a structured form, which we need to detect on one side, from backward to forward, if P3[i] >= (n-i+1), stating that item I has exceeded (n-i+1) * (n-i), then it should be rounded up to (n-i+1)!, that is p3[i-1]+= 1, and so on, the rounding of the 1th bit is no longer considered.
Finally get the correct p3[] sequence, and then through the tree array + two points in the complexity of the NLOGNLOGN will p3 each bit corresponds to the results of each number of permutations, that is, the above for Rank (p) of the anti-operation, not fine, think about it.
Code:
#include <iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<vector>#include<queue>using namespacestd;#defineN 200107intP1[n],p2[n],p3[n],c[n];intN;intLowbit (intx) {returnx&-x;}voidModifyintXintval) { while(x <= n+Ten) {C[x]+=Val; X+=lowbit (x); }}intGetsum (intx) { intres =0; while(X >0) {res+=C[x]; X-=lowbit (x); } returnRes;}intMain () {inti,j,x; while(SCANF ("%d", &n)! =EOF) {memset (c,0,sizeof(c)); for(i=1; i<=n;i++) Modify (I,1); for(i=1; i<=n;i++) {scanf ("%d",&x); X++; P1[i]= Getsum (X-1); Modify (x,-1); } memset (c,0,sizeof(c)); for(i=1; i<=n;i++) Modify (I,1); for(i=1; i<=n;i++) {scanf ("%d",&x); X++; P2[i]= Getsum (X-1); Modify (x,-1); } memset (P3,0,sizeof(p3)); for(i=n;i>=1; i--) {P3[i]+ = p1[i]+P2[i]; if(P3[i] >= (n-i+1) ) {P3[i]= p3[i]-(n-i+1); if(I! =1) p3[i-1]++; }} memset (C,0,sizeof(c)); for(i=1; i<=n;i++) Modify (I,1);//For (i=1;i<=n;i++)//cout<<p3[i]<< "";//cout<<endl; for(i=1; i<=n;i++) { intLow =1, high =N; while(Low <=High ) { intMid = (Low+high)/2; if(Getsum (mid-1) >P3[i]) high= mid-1; Else if(Getsum (mid-1) = = P3[i] && getsum (mid)-getsum (mid-1) ==1) High= mid-1; Else if(Getsum (mid-1) = = P3[i] && getsum (mid)-getsum (mid-1) <1) Low= mid+1; Else if(Getsum (mid-1) <P3[i]) Low= mid+1; } modify (Low,-1); printf ("%d", low-1); } puts (""); } return 0;}
View Code
The code written in the game is not the most simplified, there is a lot of redundancy and superfluous place.
Codeforces Round #285 (Div.1 B & Div.2 D) Misha and permutations summation--two points + Tree array