您的位置:首页 > 其它

bzoj3702 二叉树

2017-05-31 15:29 197 查看
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3702

【题解】

卧槽这竟然是bzoj的题(没想到)

啊很明显我们对于每个节点 判断一下两边交换/不交换哪个逆序对贡献的少就行了

至于这个逆序对贡献啊?线段树合并!

啊我不会线段树合并啊?启发式合并(dsu on tree)

# include <vector>
# include <stdio.h>
# include <assert.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, siz, rt, ch[M][2], siz2;
int val[M], a[M], m, sz[M], sz2[M];
vector<int> ps;

struct BIT {
int c[M], n;
# define lb(x) (x&(-x))
inline void set(int _n) {
n = _n;
memset(c, 0, sizeof c);
}
inline void edt(int x, int d) {
for (; x<=n; x+=lb(x)) c[x] += d;
}
inline int sum(int x) {
int ret=0;
for (; x; x-=lb(x)) ret += c[x];
return ret;
}
inline int sum(int l, int r) {
if(l>r) return 0;
return sum(r)-sum(l-1);
}
}T;

inline void dfs(int &x) {
int t; scanf("%d", &t);
if(t == 0) x = ++siz;
else x = ++siz2;
sz[x] = 1;
if(t == 0) {
dfs(ch[x][0]);
dfs(ch[x][1]);
sz[x] += sz[ch[x][0]] + sz[ch[x][1]];
sz2[x] = sz2[ch[x][0]] + sz2[ch[x][1]];
} else {
sz2[x] = 1;
val[x] = t;
ps.push_back(t);
}
}

bool big[M];
ll cura = 0, curb;
inline void calc(int x) {
if(val[x] != 0) {
cura += T.sum(val[x]+1, n);
curb += T.sum(val[x]-1);
return ;
}
if(!big[ch[x][0]]) calc(ch[x][0]);
if(!big[ch[x][1]]) calc(ch[x][1]);
}

inline void del(int x, int d) {
if(x <= n) {
T.edt(val[x], d);
return ;
}
if(!big[ch[x][0]]) del(ch[x][0], d);
if(!big[ch[x][1]]) del(ch[x][1], d);
}

ll ans = 0;
inline void dsu(int x, bool kep) {
if(x <= n) {
if(kep) T.edt(val[x], 1);
return;
}
int bc, sc;
if(sz[ch[x][0]] > sz[ch[x][1]]) bc = ch[x][0], sc = ch[x][1];
else bc = ch[x][1], sc = ch[x][0];
dsu(sc, 0);
dsu(bc, 1);
//    printf("x=%d, query=%d\n", x, T.sum(1, n));
big[bc] = 1;
cura = curb = 0;
calc(x); del(x,1);
ans += min(cura, curb);
big[bc] = 0;
if(kep == 0) del(x,-1);
}

int main() {
cin >> n;
siz = n; dfs(rt);
T.set(n);
sort(ps.begin(), ps.end());
ps.erase(unique(ps.begin(), ps.end()), ps.end());
for (int i=1; i<=siz; ++i)
if(val[i] != 0) val[i] = lower_bound(ps.begin(), ps.end(), val[i]) - ps.begin() + 1;
//    for (int i=1; i<=siz; ++i) printf("x=%d, ls=%d, rs=%d\n", i, ch[i][0], ch[i][1]);
dsu(rt, 1);
cout << ans << endl;
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: