前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BZOJ2212: [Poi2011]Tree Rotations(线段树合并)

BZOJ2212: [Poi2011]Tree Rotations(线段树合并)

作者头像
attack
发布2018-12-04 11:13:07
2970
发布2018-12-04 11:13:07
举报

题意

题目链接

Sol

线段树合并为什么我会在这个时候学这种东西

就是暴力合并两棵线段树(必须动态开节点),遇到空节点就返回

可以证明,对于\(m\)个仅有一个元素,权值范围在\([1, n]\)的线段树合并的复杂度为\(mlogn\)

对于此题来说,显然子树内与子树外互不影响,因此暴力判断一下翻转之后会不会变优就行了

#include<bits/stdc++.h>
#define LL long long 
using namespace std;
const int MAXN = 1e7 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, val[MAXN], ls[MAXN], rs[MAXN], tot;
LL ans, c1, c2;
int newtree(int l, int r, int x) {
    val[++tot] = 1;
    if(l == r) return tot;
    int mid = l + r >> 1, now = tot;
    if(x <= mid) ls[now] = newtree(l, mid, x);
    else rs[now] = newtree(mid + 1, r, x);
    return now;
}
int merge(int l, int r, int x, int y) {
    if(!x || !y) return x + y;
    if(l == r) {val[++tot] = val[x] + val[y]; return tot;}
    c1 += 1ll * val[rs[x]] * val[ls[y]], c2 += 1ll * val[ls[x]] * val[rs[y]];
    int mid = l + r >> 1, now = ++tot;
    ls[now] = merge(l, mid, ls[x], ls[y]);
    rs[now] = merge(mid + 1, r, rs[x], rs[y]);
    val[now] = val[x] + val[y];
    return now;
}
int dfs() {
    int v = read();
    if(v) return newtree(1, N, v);
    int now = merge(1, N, dfs(), dfs());
    ans += min(c1, c2); c1 = c2 = 0;
    return now;
}
int main() {
    N = read();
    dfs();
    cout << ans;
    return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-10-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题意
  • Sol
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档