LZU 第四届校赛

链接:http://oj.lovelyanqi.com/contest/3

H:

首先翻译一下权值,意思就是将原来排列中的 (i) 换成了权值排名为第 (i) 个的数,
我们发现,只需要20位的排列就可以占满 (10^18) 个排名了,所以只需要先把排列前面所有的位置答案算好,
然后暴力统计排列的后 (20) 位即可
如果不满 (20) 位就更可以暴力了

时间复杂度 (O(20*m))

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 100010;

int n, m;
ll ans = 0, b[maxn], fac[30], p[maxn];


struct Num{
	int id, a;
	
	bool operator < (const Num &x) const{
		return a < x.a;
	}
}a[maxn];

int v[30], c[30];
ll calc(ll sum){
	for(int i = 1 ; i <= 20 ; ++i) v[i] = 1;
	ll tmp = sum;
	
	for(int i = 1 ; i <= 20 ; ++i){
		int t = tmp / fac[20 - i];
		int cnt = 0;
		for(int j = 1 ; j <= 20 ; ++j){
			if(v[j]){
				if(cnt == t){
					c[i] = j;
					v[j] = 0;
					break;
				}
				++cnt;
			}
		}
		tmp %= fac[20 - i];
	}
//	for(int i = 1 ; i <= 19 ; ++i) printf("%d ", c[i]); printf("
");
	
	if(n < 20){
		int d = 20 - n;
		for(int i = 1 ; i <= n ; ++i){
			p[i] = a[c[i + d] - d].id;
		}
	} else{
		int d = n - 20;
		for(int i = n - 19 ; i <= n ; ++i){
			p[i] = a[c[20 - (n - i)] + d].id;
		}
	}
	
//	for(int i = 1 ; i <= n ; ++i) printf("%d ", p[i]); printf("
");
	
	ll res = 0;

	if(n < 20) {
		for(int i = 1 ; i <= n ; ++i){
			ll f = (i & 1) ? 1ll : -1ll;
			res += f * p[i];
		} 
	} else{
		for(int i = n - 19 ; i <= n ; ++i){
			ll f = (i & 1) ? 1ll : -1ll;
			res += f * p[i];
		}	
	}
	
	return res; 
}

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }

int main(){
	fac[0] = 1; ll sum = 0;
	for(int i = 1 ; i <= 20 ; ++i) fac[i] = fac[i - 1] * i;
//	for(int i = 1 ; i <= 20 ; ++i) printf("%lld ", fac[i]); printf("
");

	n = read();
	for(int i = 1 ; i <= n ; ++i) a[i].a = read(), a[i].id = i; 
	
	sort(a + 1, a + 1 + n);
	for(int i = 1 ; i <= n ; ++i) p[i] = a[i].id;
	if(n >= 20){
		for(int i = 1 ; i <= n - 20 ; ++i){
			ll f = (i & 1) ? 1ll : -1ll; 
			sum += f * p[i];
		}	
	}
//	for(int i = 1 ; i <= n ; ++i) printf("%d ", a[i].id); printf("
");

	m = read();
	for(int i = 1 ; i <= m ; ++i) b[i] = read();
	
	if(n < 20){
		ans = 0;
	} else{
		ans = sum * m;
	}
	for(int i = 1 ; i <= m ; ++i){
		--b[i];
		ans += calc(b[i]);
	}
	
	printf("%lld
", ans); 
	
	return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/14025352.html