loj2163 / bzoj2212 / P3521 [POI2011]ROT-Tree Rotations(线段树合并)
P3521 [POI2011]ROT-Tree Rotations
loj2163 [POI2011]ROT-Tree Rotations(数据加强)
(loj的数据套了个fread优化才过...)
显然地,对于一棵线段树(树根设为$rt$),是否翻转它的子树的子树,对于跨$mid$的逆序对数量没有影响。
那么我们可以层层统计(设左右子树为$lc,rc$):
不翻转时,该层(跨$mid$)的逆序对:$a[a[a[rt].lc].rc].sum*a[a[a[rt].rc].lc].sum$
翻转时,逆序对数量:$a[a[a[rt].lc].lc].sum*a[a[a[rt].rc].rc].sum$
递归处理即可。
重点是合并线段树:
前提:两棵动态开点线段树
实现(将树$pr$合并到$o$上):
void merge(int &o,int pr){
if(!o||!pr) {o=o+pr;return;}//一棵为空则返回另一边
a[o].sum+=a[pr].sum;
.......//结算信息
merge(a[o].lc,a[pr].lc);
merge(a[o].rc,a[pr].rc); //递归合并
}
蓝后就结束了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#define re register
using namespace std;
typedef long long ll;
char gc(){
static char buf[],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,,stdin),p1==p2)?EOF:*p1++;
}
void read(int &x){
char c=gc();x=;
while(!isdigit(c)) c=gc();
while(isdigit(c)) x=(x<<)+(x<<)+(c^),c=gc();
}//以上读入优化
ll min(ll &a,ll &b){return a<b?a:b;}
struct node{int sum,lc,rc;}a[];
int n,u,rt; ll res1,res2,ans;
void update(int &o,int l,int r,int v){
if(!o) o=++u;
++a[o].sum;
if(l==r) return;
int mid=l+((r-l)>>);
if(v<=mid) update(a[o].lc,l,mid,v);
else update(a[o].rc,mid+,r,v);
}
void merge(int &o,int pr){//把o/pr当作左/右子树,合并到左子树
if(!o||!pr) {o=o+pr;return;}
a[o].sum+=a[pr].sum;
res1+=1ll*a[a[o].lc].sum*a[a[pr].rc].sum; //翻转:lc->lc 和 rc->rc 之间的逆序对数
res2+=1ll*a[a[o].rc].sum*a[a[pr].lc].sum; //不翻转:lc->rc 和 rc->lc 之间的逆序对数
merge(a[o].lc,a[pr].lc); //合并线段树,并计算 lc->lc 和 rc->lc 之间的逆序对数
merge(a[o].rc,a[pr].rc); //同上
}
void dfs(int &x){//题意的神奇递归输入
int q,lc,rc; read(q);
if(!q){
dfs(lc); dfs(rc);
res1=res2=;
merge(x=lc,rc);//合并
ans+=min(res1,res2);//选代价小的
}else update(x=,,n,q);//给叶子结点单独建一棵线段树,后面再合并
}
int main(){
// freopen("P3521_2.in","r",stdin);
read(n); dfs(rt);
printf("%lld",ans);
return ;
}
loj2163 / bzoj2212 / P3521 [POI2011]ROT-Tree Rotations(线段树合并)的更多相关文章
- 【BZOJ2212】[Poi2011]Tree Rotations 线段树合并
[BZOJ2212][Poi2011]Tree Rotations Description Byteasar the gardener is growing a rare tree called Ro ...
- BZOJ2212 [Poi2011]Tree Rotations 线段树合并 逆序对
原文链接http://www.cnblogs.com/zhouzhendong/p/8079786.html 题目传送门 - BZOJ2212 题意概括 给一棵n(1≤n≤200000个叶子的二叉树, ...
- bzoj2212[Poi2011]Tree Rotations [线段树合并]
题面 bzoj ans = 两子树ans + min(左子在前逆序对数, 右子在前逆序对数) 线段树合并 #include <cstdio> #include <cstdlib> ...
- BZOJ2212【POI2011】ROT:Tree Rotation 线段树合并
题意: 给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求叶子遍历序的逆序对最少. 分析: 求逆序对我们可以想到权值线段树,所以我们对每个点建一颗线段树(为了避免空间爆炸,采 ...
- BZOJ.2212.[POI2011]Tree Rotations(线段树合并)
题目链接 \(Description\) 给定一棵n个叶子的二叉树,每个叶节点有权值(1<=ai<=n).可以任意的交换两棵子树.问最后顺序遍历树得到的叶子权值序列中,最少的逆序对数是多少 ...
- [bzoj2212]Tree Rotations(线段树合并)
解题关键:线段树合并模板题.线段树合并的题目一般都是权值线段树,因为结构相同,求逆序对时,遍历权值线段树的过程就是遍历所有mid的过程,所有能求出所有逆序对. #include<iostream ...
- Bzoj P2212 [Poi2011]Tree Rotations | 线段树合并
题目链接 通过观察与思考,我们可以发现,交换一个结点的两棵子树,只对这两棵子树内的节点的逆序对个数有影响,对这两棵子树以外的节点是没有影响的.嗯,然后呢?(っ•̀ω•́)っ 然后,我们就可以对于每一个 ...
- bzoj2212/3702 [Poi2011]Tree Rotations 线段树合并
Description Byteasar the gardener is growing a rare tree called Rotatus Informatikus. It has some in ...
- bzoj2212 Tree Rotations 线段树合并+动态开点
题目传送门 思路: 区间合并线段树的题,第一次写,对于一颗子树,无论这个子树怎么交换,都不会对其他子树的逆序对造成影响,所以就直接算逆序对就好. 注意叶子节点是1到n的全排列,所以每个权值都只会出现1 ...
- BZOJ_2212_[Poi2011]Tree Rotations_线段树合并
BZOJ_2212_[Poi2011]Tree Rotations_线段树合并 Description Byteasar the gardener is growing a rare tree cal ...
随机推荐
- jdbc链接数据库,获取表名,字段名和数据
import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import ...
- PHP之命名空间
前面的话 从广义上来说,命名空间是一种封装事物的方法.在很多地方都可以见到这种抽象概念.例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色.这个原理应用到程序设计 ...
- fedora/centos7防火墙FirewallD详解
1 使用 FirewallD 构建动态防火墙 1.1 “守护进程” 1.2 静态防火墙(system-config-firewall/lokkit) 1.3 使用 iptables 和 ip6tabl ...
- bond的操作方式
本文转自网上,版权归属原作者,原文地址 :https://www.cnblogs.com/5201351/p/4898342.html 操作系统:CentOS Linux release 7.1.15 ...
- Oracle存储过程--案例
限额控制 CREATE OR REPLACE PACKAGE BODY NP_PCKG_MERCHANT_LIMIT AS PROCEDURE CHECK_LIMIT ( in_iplCode IN ...
- mysql日期处在某两个时间段之间的between比较
where SYSDATE() between '2018-08-28 09:21:48' and '2018-08-28 09:25:48' sysdate()等于2018-08-28 09:23: ...
- instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例 , 返回true或者false
<?phpclass MyClass{} class NotMyClass{}$a = new MyClass; var_dump($a instanceof MyClass);var_dump ...
- HOJ 1936&POJ 2955 Brackets(区间DP)
Brackets My Tags (Edit) Source : Stanford ACM Programming Contest 2004 Time limit : 1 sec Memory lim ...
- pandas的merge方法
数据合并时可以使用merge方法,对两个dataFrame根据某一个series合并,这个方法非常好用,只要找到了合并的标准,新的数据就可以重构出来. 1.命令: pd.merge() on:列名,j ...
- htop 分析 进程对资源的消耗
[root@d ~]# htop -hhtop 2.2.0 - (C) 2004-2018 Hisham MuhammadReleased under the GNU GPL. -C --no-col ...