https://pintia.cn/problem-sets/994805046380707840/exam/problems/1518582895035215872

题意

给你一棵树,给定树根,要求树的所有结点编号的dfs序中逆序对的数量总和,对结果模 \(10^9 + 7\)

树的结点数 \(\leq 3*10^5\)

思路

首先会想到,树的dfs序的方案数是 \(\prod_{i=1}^{n}cntson[i]\)

接下来分析什么情况下树的dfs序会产生逆序对。

把会产生逆序对的情况分为两种,第一种是两个点是祖先和子孙的关系,那么如果祖先更大,这一对点一定会产生逆序对,对答案的贡献是dfs序的方案数

第二种是两个点不是祖先和子孙的关系,又因为每个点的编号互不相同,所以它们有1/2的概率会产生逆序对,对答案的贡献是dfs序的方案数/2

那么最后的答案就是 第一种情况的数量 * 第一种情况的点对贡献 + 第二种情况的数量 * 第二种情况的点对贡献

统计第一种情况的数量:需要知道一个点的祖先中有多少比它大,可以在dfs结点时模拟一个栈,当遍历到某个点就把它入栈,遍历子结点时它就在栈中,遍历完子节点后把它出栈,然后用树状数组统计数量

第二类点,只用分析一个父亲结点的子树的情况,然后会发现它就包含了所有第二类情况

code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3e5 + 10, mod = 1e9 + 7;
int n, r;
int a[N];
vector<int> e[N];
ll fac[N], base, c[N], s, s2;
int sz[N]; // 第二类点:不是祖先也不是子孙的点 ll qpow(ll a,ll b){
ll ans=1;
while(b){
if(b%2){
ans*=a;
ans%=mod;
}
a*=a;
a%=mod;
b/=2;
}
return ans;
} inline int lowbit(int x) {return x & -x;} void upd(int x, ll k){
while(x<=n){
c[x]+=k;
x+=lowbit(x);
}
} ll sum(int x){
ll res=0;
while(x){
res+=c[x];
x-=lowbit(x);
}
return res;
} void init(int n) {
fac[0] = 1;
for(int i = 1; i <= n; i++) fac[i] = fac[i - 1] * i % mod;
} void dfs(int u, int fa) {
sz[u] = 1;
s = (s + sum(n) - sum(u)) % mod;
upd(u, 1);
ll t = 0;//
int cn = 0;
for(auto v : e[u]) {
if(v == fa) continue;
dfs(v, u);
sz[u] += sz[v];
cn++;
s2 += t * sz[v]; s2 %= mod;
t += sz[v];
}
base = base * fac[cn] % mod;
upd(u, -1);
} int main() {
scanf("%d%d", &n, &r);
init(n);
for(int i = 1, u, v; i < n; i++) {
scanf("%d%d", &u, &v);
e[u].push_back(v);
e[v].push_back(u);
}
base = 1;
dfs(r, 0);
ll ans = s * base % mod;
// ans = (ans + (1ll * n * (n - 1) / 2 - s - s2) * base % mod * qpow(2, mod - 2) % mod) % mod;
ans = (ans + s2 * base % mod * qpow(2, mod - 2) % mod) % mod;
printf("%lld\n", ans);
// cout << "base: " << base << endl;
system("pause");
return 0;
}

最新文章

  1. Java之多态(二)
  2. 3、Python字符串和循环
  3. [LeetCode] Letter Combinations of a Phone Number
  4. Windows Sserver 2008 R2 搭建DNS配置区域与配置转发器上外网
  5. java实现excel与mysql的导入导出
  6. Android || IOS录制mp3语音文件方法
  7. bug集合
  8. uvalive 2797 Monster Trap
  9. 三十项调整助力 Ubuntu 13.04 更上一层楼
  10. C++引用变量学习
  11. 解决:安装SQl 2008为SQL Server代理服务提供的凭据无效
  12. CentOS更新源
  13. 【EXCEL-折线图】百折不挠 | 用EXCEL画出与众不同的折线图(曲线图)
  14. CentOS7.x搭建时间同步服务器
  15. 第一节:从面向对象思想(oo)开发、接口、抽象类以及二者比较
  16. 使用cookie保存用户名和密码
  17. [蓝桥杯]PREV-19.历届试题_九宫重排
  18. Python 3下Matplotlib画图中文显示乱码的解决方法
  19. [vue]webpack使用样式
  20. Java函数接口实现函数组合及装饰器模式

热门文章

  1. 首个比较研究表明维持期强柱患者减量续用TNFi疗效尚佳且药费省
  2. 配置 Vite 自动导入 ElementPlus 组件、函数、Icons、样式
  3. Idea External Libraries 没有导入依赖
  4. Optimum + ONNX Runtime: 更容易、更快地训练你的 Hugging Face 模型
  5. Linux查询CPU,内存,硬盘使用率以及网卡流量指令
  6. C#中播放mp3格式的音乐代码
  7. UIAutomator API定位元素
  8. (pymssql._pymssql.OperationalError) (8152, b&#39;String or binary data would be truncated.DB-Lib error message 20 018, severity 16:\nGeneral SQL Server error: Check messages from the SQL Server\n&#39;)
  9. cookie,session,token,drf-jwt
  10. windows下解决getAddressInfo Failed的一种办法