Solution to a problem P5367 [[template]] Cantor Expand

P5367 [template] Cantor Expand

I feel this question is probably more difficult problem to qwq between the green and blue title

First, the Los Valley Daily [yummy] On Cantor Expand

If I want to know 321 {1,2,3} is the first of several small numbers consider this:

3 is a first, when the first number is less than 3, then the number of permutations of less than 321 such as 123, 213, the number is less than 1, 2 3. So there are two 2! Months. Second look less than 2: less than the number 2 only is a 1, it is 1 1 = 1 Therefore, the number of permutations of less than 321 {1,2,3} has 2! 2 + 1! 1 = 5!. So 321 is the first of six small number. 2 2! + 1 1! + 0 * 0! Cantor is expanded.

Another example: 1324 is the number of permutations {1,2,3,4} for the first few large number: the first number is less than 1 is not 1, 0 is 0 ! 3 3 The second is less than 3 there are number 1 and 2, but 1 have been in the first place, so there is only one number 2 1 2!. The third number is 2 is less than 1 2, 1 in the first place but, it is the number 0 0 1!, So there are arranged smaller than 1324 0 . 3! + 1 2! +0 1! = 2, 1324 is the third decimal. (Excerpt from Baidu)

Violent practices

//n表示全排列长度
for(int i=1;i<=n;i++)
{
    cin>>a[i];
    int x=a[i];
    for(int j=1;j<=a[i];j++)
        x-=used[j];
    //used[j]表示j是否用过(1用过,0没用)
    used[a[i]]=1;
    a[i]=x-1;
}

Second, optimization

"We are seeing just the method has two cycle, time complexity is O (N ^ 2), the number of the left to find the number of used time-consuming.

As long as the function range and used with an array of maintenance segment tree or tree, you can only log spend time to find the left is less than the number of the number of own. "(Excerpt from Daily)

Third, the code

#include<cstdio>
using namespace std;
#define N 1000001
int n,tr[N];
long long ans,fac[N];
inline void add(int x,int k) {
    for (; x<=n; x+=x&-x) tr[x]+=k;
}
inline int query(int x) {
    int t=0;
    for (; x; x-=x&-x) t+=tr[x];
    return t;
}
int main() {
    scanf("%d",&n);
    fac[0]=1;
    for (int i=1; i<=n; i++) {
        fac[i]=fac[i-1]*i%998244353;
        add(i,1);
    }
    for (int i=1,x; i<=n; i++) {
        scanf("%d",&x);
        ans=(ans+(query(x)-1)*fac[n-i])%998244353;
        add(x,-1);
    }
    printf("%lld",ans+1);
    return 0;
}

Fourth, expand: Expand the inverse Cantor

Example {1,2,3,4,5} whole arrangement, and it has been sorted in ascending

(1) 96 to identify the number of

First with a 95 96-1

95 removal of 4! Get more than 323

There are three numbers smaller than it is four

So the first one is 4

With the removal of 23 3! Get more than 35

There are three numbers is the number smaller than 4, but it has appeared 4 before a second is so 5 (4 occurred before, the actual number 5 is smaller than 3)

5 to remove 2! Get more than 2 1

There it is smaller than the number 2 is the number 3, the third 3

By removing 1 1! Get more than 10

There are a number smaller than the number which is 2, 2 is the second

The last number is only 1

So this number is 45321 (taken from Baidu)

Guess you like

Origin www.cnblogs.com/Randolph68706/p/11200202.html