「解题报告」AGC023E Inversions
好。
首先考虑怎么计算方案数。我们考虑按照
我们设
然后考虑经典拆贡献,枚举每一对
首先假设
假如说
我们考虑维护这个东西。我们按照
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005, P = 1000000007;
int qpow(int a, int b) {
int ans = 1;
while (b) {
if (b & 1) ans = 1ll * ans * a % P;
a = 1ll * a * a % P;
b >>= 1;
}
return ans;
}
int n, a[MAXN], b[MAXN], c[MAXN];
struct SegmentTree {
struct Node {
int val, tag;
Node() : val(0), tag(1) {}
} t[MAXN << 2];
#define lc (i << 1)
#define rc (i << 1 | 1)
void tag(int i, int v) {
t[i].tag = 1ll * t[i].tag * v % P;
t[i].val = 1ll * t[i].val * v % P;
}
void pushDown(int i) { tag(lc, t[i].tag), tag(rc, t[i].tag), t[i].tag = 1; }
void mul(int a, int b, int v, int i = 1, int l = 1, int r = n) {
if (a > b) return;
if (a <= l && r <= b) return tag(i, v);
int mid = (l + r) >> 1;
pushDown(i);
if (a <= mid) mul(a, b, v, lc, l, mid);
if (b > mid) mul(a, b, v, rc, mid + 1, r);
t[i].val = (t[lc].val + t[rc].val) % P;
}
void set(int d, int v, int i = 1, int l = 1, int r = n) {
if (l == r) {
t[i].val = v;
return;
}
int mid = (l + r) >> 1;
pushDown(i);
if (d <= mid) set(d, v, lc, l, mid);
else set(d, v, rc, mid + 1, r);
t[i].val = (t[lc].val + t[rc].val) % P;
}
int query(int a, int b, int i = 1, int l = 1, int r = n) {
if (a > b) return 0;
if (a <= l && r <= b) return t[i].val;
int mid = (l + r) >> 1;
pushDown(i);
if (b <= mid) return query(a, b, lc, l, mid);
if (a > mid) return query(a, b, rc, mid + 1, r);
return (query(a, b, lc, l, mid) + query(a, b, rc, mid + 1, r)) % P;
}
} st;
struct BinaryIndexTree {
int a[MAXN];
#define lowbit(x) (x & (-x))
void add(int d, int v) {
while (d <= n) {
a[d] += v;
d += lowbit(d);
}
}
int query(int d) {
if (!d) return 0;
int ret = 0;
while (d) {
ret += a[d];
d -= lowbit(d);
}
return ret;
}
} bit;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
b[i] = i;
}
sort(b + 1, b + 1 + n, [&](int x, int y) { return a[x] < a[y]; });
int s = 1;
for (int i = 1; i <= n; i++) {
c[i] = a[b[i]] - i + 1;
if (c[i] <= 0) {
printf("0\n");
return 0;
}
s = 1ll * s * c[i] % P;
}
int ans = 0;
for (int i = 1; i <= n; i++) {
ans = (ans + 1ll * st.query(1, b[i] - 1) * qpow(2 * c[i], P - 2)) % P;
ans = (ans - 1ll * st.query(b[i] + 1, n) * qpow(2 * c[i], P - 2) % P + P) % P;
ans = (ans + 1ll * (i - bit.query(b[i]) - 1) * s) % P;
st.mul(1, n, 1ll * (c[i] - 1) * qpow(c[i], P - 2) % P);
st.set(b[i], 1ll * s * (c[i] - 1) % P);
bit.add(b[i], 1);
}
printf("%d\n", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通