ALGO-7_蓝桥杯_算法训练_逆序对
出处:http://blog.csdn.net/enjoying_science/article/details/44114035
(有难度,以后回来填坑)
阅读代码中:
#include<stdio.h>
#include<iostream>
using namespace std;
#define ForD(i,n) for(int i=n;i;i--)
#define F (100000007)
#define MAXN (2*200000+10)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;} int n,root=;/*n->叶子结点数,root->根序号?*/
struct node
{
int fa; /*父结点的下标*/
int ch[]; /*0->左树下标 1->右树下标*/
int size; /*size->当前结点含有的有效结点数*/
int c; /*当前结点的数值*/
node():size(),c(){ch[]=ch[]=fa=;} /*初始化为0*/
}a[MAXN]; /*树形数组->纪录各叶结点的数值*/ void update(int x)/*更新叶结点个数*/
{
a[x].size=a[a[x].ch[]].size+a[a[x].ch[]].size+(a[x].c>);
}
int tail=;
void pushdown(int x)/*将叶结点的父结点指向当前结点*/
{
a[a[x].ch[]].fa=a[a[x].ch[]].fa=x;
} /*创建树*/
void build(int &x)
{
if (!x) x=++tail;
scanf("%d",&a[x].c);
if (a[x].c==)
{
build(a[x].ch[]);/*创建左子树*/
build(a[x].ch[]);/*创建右子树*/
update(x);pushdown(x);/*更新当前结点的有效叶结点个数,以及父结点指向*/
}else a[x].size=;
} void rotate(int x)/*旋转*/
{
int y=a[x].fa,z=a[y].fa;
bool p=a[y].ch[]==x;
if (z) /*有爷爷*/
{
if (a[z].ch[]==y) /*未旋转*/
a[z].ch[]=x;/*将子树提拔为父树(升序)*/
else
a[z].ch[]=x; /*还原状态*/
}
a[x].fa=z,a[y].fa=x;/*当前结点与父结点交换(父结点指向)*/
if (a[x].ch[p]) /*原子树是否有右树(隔代转移)*/
a[a[x].ch[p]].fa=y;
a[y].ch[p^]=a[x].ch[p];
a[x].ch[p]=y; /*父树移至子树的右端(右树)*/
update(y); /*更新旋转后,子树的结点的有效结点数*/
} void splay(int x)
{
while (a[x].fa)/*不为根结点*/
{
int y=a[x].fa,z=a[y].fa;
if (z) /*有爷爷*/
if ((a[y].ch[]==x)^(a[z].ch[]==y)) rotate(x);/*旋转*/
else rotate(y);
rotate(x);
}
update(x);
}
void ins(long long &tot,int x,int y)
{
a[x].size++; /*插入+1*/
if (a[y].c<=a[x].c) /*是逆序对*/
{
if (a[x].ch[]) /*左树有子*/
ins(tot,a[x].ch[],y);
else /*左树无子*/
a[y].fa=x,splay(a[x].ch[]=y);/*右数插入到左树子*/
}
else
{
tot+=a[a[x].ch[]].size+(a[x].c>);
if (a[x].ch[]) ins(tot,a[x].ch[],y);
else a[y].fa=x,splay(a[x].ch[]=y);
}
} int q[MAXN],size; void clac(int x,int y)
{
if (a[y].ch[]) clac(x,a[y].ch[]);
if (a[y].c) q[++size]=y;
if (a[y].ch[]) clac(x,a[y].ch[]);
} long long merge(bool &lor,int z)/*分治*/
{
int x=a[z].ch[],y=a[z].ch[];
if (a[x].size<a[y].size) /*判断叶结点多的往前调(平衡树?)*/
swap(x,y); a[x].fa=;a[y].fa=;q[]=y;
size=;clac(x,y);
long long tot=; /*最少逆序对*/
ForD(i,size) /*循环(子结点数)次*/
{
int now=q[i];
a[now].ch[]=a[now].ch[]=a[now].fa=;
a[now].size=;
ins(tot,x,now);
x=now;
}
a[x].fa=z;
a[z].ch[]=,a[z].ch[]=x;
return tot;
} long long qur(int &x)
{
if (a[x].c) return ;/*若根结点没有叶结点,则逆序对为0*/
else
{
long long lson=a[a[x].ch[]].size,rson=a[a[x].ch[]].size,ls=qur(a[x].ch[]),rs=qur(a[x].ch[]);
bool lor=;
long long ms=merge(lor,x);
return ls+rs+min(lson*rson-ms,ms);
}
}
int main()
{
scanf("%d",&n);
build(root);
cout<<qur(root)<<endl;
return ;
}
ALGO-7_蓝桥杯_算法训练_逆序对的更多相关文章
- Java实现蓝桥杯VIP算法训练 数组逆序排列
试题 算法训练 数组逆序排列 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 编写一个程序,读入一组整数(不超过20个),并把它们保存在一个整型数组中.当用户输入0时,表示输入结束. ...
- [蓝桥杯]ALGO-20.算法训练_求先序排列
问题描述 给出一棵二叉树的中序与后序排列.求出它的先序排列.(约定树结点用不同的大写字母表示,长度<=). 输入格式 两行,每行一个字符串,分别表示中序和后序排列 输出格式 一个字符串,表示所求 ...
- [蓝桥杯]ALGO-16.算法训练_进制转换
问题描述 我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式.例如:123可表示为 1*102+2*101+3*100这样 ...
- [蓝桥杯]ALGO-15.算法训练_旅行家的预算
问题描述 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的).给定两个城市之间的距离D1.汽车油箱的容量C(以升为单位).每升汽油能行驶的距离D2.出发点每升汽油价格P和沿 ...
- [蓝桥杯]ALGO-124.算法训练_数字三角形
问题描述 (图3.1-1)示出了一个数字三角形. 请编一个程序计算从顶至底的某处的一条路 径,使该路径所经过的数字的总和最大. ●每一步可沿左斜线向下或右斜线向下走: ●<三角形行数≤: ●三角 ...
- [蓝桥杯]ALGO-122.算法训练_未名湖边的烦恼
问题描述 每年冬天,北大未名湖上都是滑冰的好地方.北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩. 每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个.现在 ...
- [蓝桥杯]ALGO-116.算法训练_最大的算式
问题描述 题目很简单,给出N个数字,不改变它们的相对位置,在中间加入K个乘号和N-K-1个加号,(括号随便加)使最终结果尽量大.因为乘号和加号一共就是N-1个了,所以恰好每两个相邻数字之间都有一个符号 ...
- [蓝桥杯]ALGO-101.算法训练_图形显示
问题描述 编写一个程序,首先输入一个整数,例如5,然后在屏幕上显示如下的图形(5表示行数): * * * * * * * * * * * * * * * 题目描述 代码如下: #include < ...
- [蓝桥杯]ALGO-97.算法训练_排序
题目描述: 问题描述 编写一个程序,输入3个整数,然后程序将对这三个整数按照从大到小进行排列. 输入格式:输入只有一行,即三个整数,中间用空格隔开. 输出格式:输出只有一行,即排序后的结果. 输入输出 ...
- [蓝桥杯]ALGO-92.算法训练_前缀表达式
问题描述 编写一个程序,以字符串方式输入一个前缀表达式,然后计算它的值.输入格式为:“运算符 对象1 对象2”,其中,运算符为“+”(加法).“-”(减法).“*”(乘法)或“/”(除法),运算对象为 ...
随机推荐
- python字典{}大括号
#字典 info = { 'name1':'jack', 'name2':'rose', 'name3':'tom', 'name4':'jerry', 'name5':'james' } info[ ...
- C语言define 可以提高程序运行的速度
define的优缺点 优点 提高了程序的可读性,同时也方便进行修改: 提高程序的运行效率:使用带参的宏定义既可完成函数调用的功能,又能避免函数的出栈与入栈操作,减少系统开销,提高运行效率: 3.宏是由 ...
- 《Python》 面向对象三大特性之多态、封装
一.多态 1.什么是多态? 一个类表现出的多种状态:通过继承来实现的 在Java中的表现:在一个函数中需要给参数指定数据类型,如果这个地方可以接收两个以上类型的参数,那么这些类型应该有一个父类,这个父 ...
- slice,Array.prototype.slice,Array.protyotype.slice.call
slice 特点:基于当前数组中的一或多个项创建一个新数组.[原数组不会被修改] 返回结果:返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象. 语法: arr.slice() ...
- 超级好用的C++万能头文件
#include<bits/stdc++.h>包含了目前c++所包含的所有头文件 对比: #include <iostream> #include <cstdio> ...
- js之表单记忆功能
在项目中,我们难免会遇到希望相同用户操作本次打开页面时可以展现或者自动记录上次登录系统点击过的的复选框,单选按钮等操作的状态,也就是表单记忆功能,这时,一个很重要的技术便派上了用场,即cookie. ...
- 15款Cocos2d-x游戏源码
(1)用cocos2d-x开发的中国象棋游戏源码 使用Cocos2d-X2.2.3开发的一款中国象棋游戏,游戏中可以实现.新局面.悔棋.游戏音乐.胜利后会显示游戏结果. 源码下载:http://www ...
- Android Kernel save defalut config
/********************************************************************************* * Android Kernel ...
- ipAllocate_and_linkState_hacking
#!/bin/bash # Author: Joshua Chen # Date: Jun # Location: Shenzhen #. 解读这两个程序是因为程序中包含了大部分shell脚本的基本语 ...
- HDU 1234:开门人和关门人
开门人和关门人 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Su ...