zoukankan      html  css  js  c++  java
  • Loj#6432「PKUSC2018」真实排名(二分查找+组合数)

    题面

    Loj

    题解

    普通的暴力是直接枚举改或者不改,最后在判断最后对哪些点有贡献。

    而这种方法是很难优化的。所以考虑在排序之后线性处理。首先先假设没有重复的元素

    struct Node { int poi, id; } a[N];
    bool operator < (const Node &a, const Node &b) { return a.poi < b.poi; }
    bool operator < (const Node &a, const int &b) { return a.poi < b; }
    bool operator < (const int &a, const Node &b) { return a < b.poi; }
    
    int main() {
        read(n);
    	for(int i = 1; i <= n; ++i) read(a[i].poi), a[i].id = i;
    	sort(a + 1, a + n + 1);
    }
    

    对于一个点,我们同样是枚举它改或者不改,但是,接着我们来判断哪些点的变化可以对这个点产生贡献,


    决策1:不改

    不改的话,那么这个元素后面的元素不管变还是不变都可以产生贡献,假设当前处理到$i$,则其后面有$n-i$个元素。

    接着考虑前面的元素,前面的元素改变可以对它产生贡献当且仅当它小于$a_i/2$。这里可以使用二分查找。假设一共有$site$个元素满足上面这个条件。

    则这个决策所产生的贡献为:$C_{n-i+site}^k$


    决策2:改

    当这个元素改的时候,怎么保证它的$rank$不变呢?那么就要保证区间$[a_i,2a_i]$这个区间内的所有数字都要变。同样可以二分来确定这个区间内有多少个元素。假设右界为$tmp$,则有$tot=tmp-i+1$个元素是必须要变的

    则这个决策所产生的贡献为:$C_{n-tot}^{k-tot}$


    重复的元素

    之前的所有决策都是在元素不重复的情况下计算的贡献。那么当元素重复时,怎么计算呢?假设现在同一个元素已经出现了$cf$次。

    考虑不改的决策,由于$rank$的含义是大于等于它的数不变,所以这个决策的贡献变为:$C_{n-i+site+cf-1}^k$

    接着考虑改变的决策,同样,根据$rank$的定义,这些重复的数字也需要改变。所以$tot$变为:
    $$
    tot=tmp-i+1+cf-1=tmp-i+cf
    $$


    接着还有一些细节,比如对于$0$的特判(直接就是$C(n,k)$)之类的

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using std::lower_bound;
    using std::upper_bound;
    using std::min; using std::max;
    using std::swap; using std::sort;
    typedef long long ll;
    
    template<typename T>
    void read(T &x) {
        int flag = 1; x = 0; char ch = getchar();
        while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
        while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
    }
    
    const int N = 1e5 + 10, P = 998244353;
    int n, k, ret[N], fac[N], inv[N];
    struct Node { int poi, id; } a[N];
    bool operator < (const Node &a, const Node &b) { return a.poi < b.poi; }
    bool operator < (const Node &a, const int &b) { return a.poi < b; }
    bool operator < (const int &a, const Node &b) { return a < b.poi; }
    inline void add(int &x) { ++x; if(x == P) x = 0; }
    
    int find(double val, int site) {
    	int l = 1, r = site - 1, ret = 0;
    	while(l <= r) {
    		int mid = (l + r) >> 1;
    		if(1. * a[mid].poi < val) ret = mid, l = mid + 1;
    		else r = mid - 1; 
    	} return ret;
    }
    
    int C(int n, int m) {
    	if(n < m) return 0;
    	return (int)(1ll * (1ll * fac[n] * inv[m] % P) * inv[n - m] % P);
    }
    
    int qpow(int a, int b) {
    	int ret = 1;
    	for(; b; b >>= 1, a = 1ll * a * a % P) if(b & 1) ret = 1ll * ret * a % P;
    	return ret;
    }
    
    int main () {
    	read(n), read(k), fac[0] = inv[0] = 1;
    	for(int i = 1; i <= n; ++i) fac[i] = 1ll * fac[i - 1] * i % P;
    	inv[n] = qpow(fac[n], P - 2);
    	for(int i = n; i >= 1; --i) inv[i - 1] = 1ll * inv[i] * i % P;
    	for(int i = 1; i <= n; ++i) read(a[i].poi), a[i].id = i;
    	sort(a + 1, a + n + 1);
    	for(int i = 1, cf = 0; i <= n; ++i) {
    		if(a[i].poi == 0) { ret[a[i].id] = C(n, k); continue; }
    		int site = find(1. * a[i].poi / 2., i);
    		if(a[i].poi == a[i - 1].poi) ++cf;
    		else cf = 1;
    		(ret[a[i].id] += C(site + n - i + cf - 1, k)) %= P;//改的决策
    		int tmp = lower_bound(a + i + 1, a + n + 1, a[i].poi * 2) - a - 1;
    		if(tmp != -1) {
    			int tot = tmp - i + cf;
    			if(k >= tot) (ret[a[i].id] += C(n - tot, k - tot)) %= P;
    		}//不改的决策
    	}
    	for(int i = 1; i <= n; ++i) printf("%d
    ", ret[i]);
    	return 0;
    } 
    
  • 相关阅读:
    leetcode--Recover Binary Search Tree
    leetcode--Construct Binary Tree from Preorder and Inorder Traversal
    leetcode---Construct Binary Tree from Inorder and Postorder Traversal
    leetcode---Trapping Rain Water
    leetcode--Balanced Binary Tree
    leetcode--Clone Graph
    leetcode--Longest Consecutive Sequence
    leetcode --Jump Game
    计算机组成原理 8 中断和异常
    计算机网络 5.6-5.8 TCP/UDP
  • 原文地址:https://www.cnblogs.com/water-mi/p/10287346.html
Copyright © 2011-2022 走看看