• AGC023E


    Description

    (n le 2*10^5)
    给定限制序列 (A)
    求满足 (P_ile A_i) 的所有排列中
    逆序对个数的和

    Solution

    考虑知道一个 (A) 序列时怎么计算排列个数
    (C[i]) 表示 (Age i) 的个数
    然后依次决定 (n, n-1, cdots 1) 填在哪里
    (k) 时有 (C[k]) 个可选位置, 其中 (n-k) 被占用
    因此总排列个数为 (prod_{k=1}^n C[k]-(n-k))
    不难证明无解时该式返回0

    用期望线性性去统计答案
    考虑 (i < j, P_i>P_j)
    (A_ile A_j) 时, 可知 (P_jle A_i), 把 (A_j) 改为 (A_i), 此时的所有排列中有一半是满足逆序对的
    (A_igt A_j) 时, 转为统计 (P_i<P_j) 的方案数, 用总的去减这个就好了

    注意到修改时把 ((A_j, A_i])(C) 都减了一, 定义这个是 (C')
    按权值从大到小枚举 (A_j)
    我们要求的是 (suff[A_i+1] * C'[A_j+1..A_i] * pref[A_j] * sign(j<i))
    按标号维护线段树, 第一项维护在线段树里, 第二项通过打标记维护

    Code

    #include <bits/stdc++.h>
    using namespace std;
    #define ri rd<int>
    #define rep(i, a, b) for (int i = (a), _ = (b); i <= _; ++i)
    #define per(i, a, b) for (int i = (a), _ = (b); i >= _; --i)
    #define For(i, a, b) for (int i = (a), _ = (b); i < _; ++i)
    const int maxN = 2e5 + 7;
    typedef long long LL;
    const LL O = 1e9 + 7;
    
    template<class T> T rd() {
    	bool f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = 0;
    	T x = 0; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return f ? x : -x;
    }
    
    int n;
    struct Node {
    	int v, i;
    	inline bool operator < (const Node &y) const {
    		return v > y.v;
    	}
    }a[maxN];
    LL c[maxN], d[maxN];
    LL C[maxN], sufC[maxN];
    
    namespace Seg {
    	const int maxN = ::maxN << 1;
    	struct Node;
    	typedef Node* node;
    	struct Node {
    		node lc, rc;
    		int l, mid, r;
    		int sz;
    		LL sum, tag;
    		bool havtag;
    		Node(int _sz = 0, LL _sum = 0) : sz(_sz), sum(_sum) { havtag = false; }
    
    		Node operator + (const Node &v) const {
    			return Node(sz + v.sz, (sum + v.sum) % O);
    		}
    
    		void totag(LL d) {
    			(sum *= d) %= O;
    			if (!havtag) havtag = true, tag = 1;
    			(tag *= d) %= O;
    		}
    
    		void pushdown() {
    			if (havtag) {
    				lc->totag(tag);
    				rc->totag(tag);
    				havtag = false;
    			}
    		}
    	}*rt, pool[maxN], *tpool = pool;
    
    	void build(node &x, int l, int r) {
    		x = tpool++;
    		x->l = l, x->r = r, x->mid = (l + r) >> 1;
    		if (l == r) return;
    		build(x->lc, l, x->mid);
    		build(x->rc, x->mid+1, r);
    	}
    
    	void init() {
    		build(rt, 1, n);
    	}
    
    	void ins(node x, int to, LL d) {
    		x->sz++;
    		(x->sum += d) %= O;
    		if (x->l == x->r) return;
    		x->pushdown();
    		if (to <= x->mid) ins(x->lc, to, d);
    		else ins(x->rc, to, d);
    	}
    
    	void ins(int x, LL d) {
    		ins(rt, x, d);
    	}
    
    	Node get(node x, int l, int r) {
    		if (l <= x->l && x->r <= r) return *x;
    		x->pushdown();
    		if (r <= x->mid) return get(x->lc, l, r);
    		if (x->mid < l) return get(x->rc, l, r);
    		return get(x->lc, l, x->mid) + get(x->rc, x->mid+1, r);
    	}
    
    	Node get(int l, int r) {
    		if (l > r) return Node();
    		return get(rt, l, r);
    	}
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("a.in", "r", stdin);
    #endif
    
    	n = ri();
    	rep (i, 1, n) {
    		c[a[i].v = ri()]++;
    		a[i].i = i;
    	}
    
    	per (i, n, 1) c[i] += c[i+1];
    	rep (i, 1, n) {
    		c[i] = c[i] - (n-i);
    		d[i] = c[i] - 1;
    	}
    	sufC[n] = 1; per (i, n-1, 0) sufC[i] = sufC[i+1] * c[i+1] % O;
    	C[0] = 1; rep (i, 1, n) C[i] = C[i-1] * c[i] % O;
    
    	Seg::init();
    	sort(a+1, a+n+1);
    	LL ans = 0, cnt = 0;
    	for (int v = n, i = 1; v; --v) {
    		LL res = 0;
    		for (; i <= n && a[i].v == v; ++i) {
    			Seg::Node tp = Seg::get(1, a[i].i-1);
    			res -= tp.sum;
    			cnt += tp.sz;
    			tp = Seg::get(a[i].i+1, n);
    			res += tp.sum;
    			Seg::ins(a[i].i, sufC[v]);
    		}
    		ans += res % O * C[v] % O;
    		Seg::rt->totag(d[v]);
    	}
    	ans = ans % O * (O+1) / 2 % O;
    	ans += cnt % O * C[n] % O;
    	printf("%lld
    ", (ans % O + O) % O);
    
    	return 0;
    }
    
  • 相关阅读:
    mysql怎么在已建好的表中添加自增序列
    IDEA报错: Invalid bound statement (not found): com.test.mapper.UserMapper.selectByPrimaryKey(转发:https://www.cnblogs.com/woshimrf/p/5138726.html)
    Windows下重置MySQL密码(最开始是因为Access denied for user 'root'@'localhost'这个原因,无法登陆 'root'@'localhost')
    数组逆转
    选择、插入、冒泡排序
    线性单链表
    顺序队列
    栈的应用----表达式求值
    顺序表的应用---若瑟夫问题
    顺序栈
  • 原文地址:https://www.cnblogs.com/acha/p/9036396.html
Copyright © 2020-2023  润新知