P3521 [POI2011]ROT-Tree Rotations(线段树合并)
一句话题意(不用我改了.....):给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少。
......这题输入很神烦呐。。。
给你一棵二叉树的dfs序(考场上没发现2333),只有叶子结点有值,然后求逆序对大小
在考场上,建树建了好久,然后暴力暴了好久,然后得到了0分的好成绩呢(我真棒)
正解其实也不难想(但是当时不会权值线段树)
题解:
其实很简单,想想:对于一层的逆序对,数量是一定的。也就是说,无论怎么转当前子树,对上一层的逆序对数量是没有影响的。
挺好理解的但是还是上张图吧:

对于第二层来说,无论左边的2,3怎么改变,相对于右边4,1或1,4的逆序对个数始终不会改变。
这个性质吼啊
于是我们只需要求块内的最小逆序对个数就行了。
然后再考虑怎么求逆序对个数。
首先,权值线段树是一个桶,而且下标是有序的(废话)
然后,两课权值线段树在本题中是等价的,也就是说,左右要合并的线段树,除了维护的区间&&存储元素不一样,是满足可并线段树的条件的。
所以,对于一个区间,逆序对只需要比较左区间的右半边(桶中)数量*右区间的左半边就行了,
然后再比较swap之后的,贪心地取下去,合并下去就行了。
.....语言表述有问题,看一下这一小段代码:
ans1+=(ll )t[t[l].rs].sum*t[t[r].ls].sum;
ans2+=(ll )t[t[l].ls].sum*t[t[r].rs].sum;
就这样,比较然后加小的,最后就是总答案了。
tips:真正明白了指针的好处,好好用啊,但是得注意一下,因为指针是直接改值,有些值不能改的话,得用一个中间变量记录。
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
#define ll long long
struct tree
{
int ls,rs,sum;
}t[maxn*];
ll ans=,ans1=,ans2=;
int n,pos;
int cnt=;
void insert(int &x,int l,int r)
{
if(!x)
{
x=++cnt;
}
t[x].sum++;
if(l==r)
{
return ;
}
int mid=(l+r)>>;
if(pos<=mid)
{
insert(t[x].ls,l,mid);
}
else
{
insert(t[x].rs,mid+,r);
}
}
void merge(int &l,int r)//直接指针合并,比原来的要好写
{
if(!l||!r)
{
l=l+r;
return ;
}
t[l].sum+=t[r].sum;
ans1+=(ll )t[t[l].rs].sum*t[t[r].ls].sum;
ans2+=(ll )t[t[l].ls].sum*t[t[r].rs].sum;
merge(t[l].ls,t[r].ls);
merge(t[l].rs,t[r].rs);
}
int work(int &x)
{
int T,ls,rs;
x=;
cin>>T;
if(!T)
{
work(ls);
work(rs);
ans1=ans2=;
x=ls;//指针,得用中间变量存储
merge(x,rs);
ans+=min(ans1,ans2);
}
else
{
pos=T;
insert(x,,n);
}
}
int main()
{
scanf("%d",&n);
int t=;
work(t);
printf("%lld",ans);
return ;
}
(完)
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 [线段树合并]
题面 bzoj ans = 两子树ans + min(左子在前逆序对数, 右子在前逆序对数) 线段树合并 #include <cstdio> #include <cstdlib> ...
- BZOJ2212 [Poi2011]Tree Rotations 线段树合并 逆序对
原文链接http://www.cnblogs.com/zhouzhendong/p/8079786.html 题目传送门 - BZOJ2212 题意概括 给一棵n(1≤n≤200000个叶子的二叉树, ...
- BZOJ.2212.[POI2011]Tree Rotations(线段树合并)
题目链接 \(Description\) 给定一棵n个叶子的二叉树,每个叶节点有权值(1<=ai<=n).可以任意的交换两棵子树.问最后顺序遍历树得到的叶子权值序列中,最少的逆序对数是多少 ...
- BZOJ2212【POI2011】ROT:Tree Rotation 线段树合并
题意: 给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求叶子遍历序的逆序对最少. 分析: 求逆序对我们可以想到权值线段树,所以我们对每个点建一颗线段树(为了避免空间爆炸,采 ...
- Bzoj P2212 [Poi2011]Tree Rotations | 线段树合并
题目链接 通过观察与思考,我们可以发现,交换一个结点的两棵子树,只对这两棵子树内的节点的逆序对个数有影响,对这两棵子树以外的节点是没有影响的.嗯,然后呢?(っ•̀ω•́)っ 然后,我们就可以对于每一个 ...
- [bzoj2212]Tree Rotations(线段树合并)
解题关键:线段树合并模板题.线段树合并的题目一般都是权值线段树,因为结构相同,求逆序对时,遍历权值线段树的过程就是遍历所有mid的过程,所有能求出所有逆序对. #include<iostream ...
- 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 ...
随机推荐
- Android通过外部浏览器调用微信H5支付,Android+PHP详解
看了好多关于讲解微信H5支付开发的文章,大多数都是通过微信内部浏览器来调用支付接口(其实就是公众号支付),可能是因为H5支付接口刚开放不久吧. 微信官方体验链接:http://wxpay.wxutil ...
- mobaxterm和CRT的文件上传
版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/submarineas/article/de ...
- Selenium+PhantomJS使用时报错原因
运行下面代码:'''PhantomJS运用''' from selenium import webdriverimport time # 通过keys模拟键盘from selenium.webdriv ...
- 第3章(1) Linux内核相关概念
Linux内核的组成 1. Linux内核源代码的目录结构 arch:包含和硬件体系结构相关的代码,每种平台占一个相应的目录,如 i386.arm. arm64.powerpc.mips 等.Linu ...
- Java学习笔记之抽象类与接口
抽象类(abstract) 抽象类概述:一个类被abstract修饰表示这个类是抽象类, 自己定义方法但是不实现方法,后代去实现 抽象方法: 一个方法被abstract修饰表示这个方法是抽象方法 ...
- PHP yield代替range生成范围内的数
<?php function yieldRange($start, $limit, $step) { if ($start == $limit || $step == 0) { return $ ...
- 高通电源管理函数的power_supply的调用关系
以msm8909为例,高通的主要文件有几个: qpnp-linear-charger.c(线性充电器) qpnp-vm-bms.c(BMS管理) power_supply_core.c(power_s ...
- std::to_string
头文件 #include <string> std::string to_string( int value ); std::string to_string( long value ); ...
- linux下mqtt-client
CPATH += ../embe_mqtt/MQTTClient/srcPSRTPATH = ../embe_mqtt/MQTTPacket/src LOADPATH += -I$(CPATH)LOA ...
- vue——同一局域网内访问项目
1.想要在手机上访问本地的vue项目,首先要保证手机和电脑处在同一局域网内(连着同一个无线网) 2.将你电脑的ip设置为固定ip(ipconfig查找本地的ip,然后修改它,改为你想变的数字) 3.在 ...