HDU2838 Cow Sorting 树状数组 区间求和加逆序数的应用
可能一開始想不到逆序数,我是专门做专题往那边想才想到的,举个样例吧
数组: 9 1 0 5 4
此时到 0 的时候,我们先手写一下最小代价,然后再依照自己的推測去看看,就是当前扫到0,那么前面比它大的数有2个,所以先 部分代价为 2 * 0,然后再加上前面比它大的数 也就是9 和1 ,那么最小代价为10,发现跟手算的一样,那么 再多试几个 最后我们就发现了
对于当前数num,前面有x个比它大的数,那么走到当前一步的 最小代价为 x*num 再加上前面比它大的数之和
这样就非常easy跟树状数组扯上关系了,当前一步的逆序数 事实上就是 前面比它大的数的个数,然后同一时候又能用树状数组对于前面比它大的数求和,这样问题就完美攻克了,一開始我看n是10^5次,可能还是没经验把,认为有可能会超,所以就先离散化的做了一遍,但是总是WA,然后离散化去掉以后就过了,不知道为什么,但是用过掉的代码跑了非常多案例,发现跟离散化版本号的 答案是一样的,真心不知道哪里写错了
#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#include<cctype> #define ll long long
#define LL __int64
#define eps 1e-8 //const ll INF=9999999999999; #define inf 0xfffffff using namespace std; //vector<pair<int,int> > G;
//typedef pair<int,int> P;
//vector<pair<int,int>> ::iterator iter;
//
//map<ll,int>mp;
//map<ll,int>::iterator p; const int N = 500000 + 10; int a[N];
int aa[N];
int n; typedef struct Node {
int v;//原数字
int id;//下标
}; Node p[N]; typedef struct C {
LL sum;
int id;
}; C c[N]; void clear() {
memset(c,0,sizeof(c));
memset(aa,0,sizeof(aa));
memset(p,0,sizeof(p));
} bool cmp(Node x,Node y) {
return x.v < y.v;
} int lowbit(int x) {
return x&(-x);
}
//设原始矩阵为a,将a[i]加上val时对c所做的改动
void update(int i, int val) {
while (i <= n) {
c[i].id += val;
i += lowbit(i);
}
} void add(int i,int val) {
while(i <= n) {
c[i].sum += (1LL) * val;
i += lowbit(i);
}
} int get_sumid(int i) {
int sum = 0;
while(i > 0) {
sum += c[i].id;
i -= lowbit(i);
}
return sum;
} //求前i项元素的和
int get_sum(int i) {
int sum=0;
while (i > 0) {
sum += c[i].sum;
i -= lowbit(i);
}
return sum;
} int main() {
while(scanf("%d",&n) == 1) {
clear();
//先离散操作
for(int i=1;i<=n;i++) {
scanf("%d",&p[i].v);
a[i] = p[i].v;
p[i].id = i;//循环序号必须从1開始
}
sort(p + 1,p + n + 1,cmp);
for(int i=1;i<=n;i++)
aa[p[i].id] = i;//aa数组存了原来大小信息
LL ans = 0;
for(int i=1;i<=n;i++) {
update(aa[i],1);
add(a[i],a[i]);
int ans1 = i - get_sumid(aa[i]);//i代表当前已经插入的个数,ge_sum(aa[i])代表比aa[i]小的数个数,减去即为大的个数,即逆序数
if(ans1 != 0) {
LL ans2 = (1LL) * get_sum(n) - (1LL) * get_sum(a[i]);
ans += (1LL) * ans1 * a[i] + ans2;
}
}
printf("%I64d\n",ans);
}
return 0;
}
AC代码:
#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#include<cctype> #define ll long long
#define LL __int64
#define eps 1e-8 //const ll INF=9999999999999; #define inf 0xfffffff using namespace std; //vector<pair<int,int> > G;
//typedef pair<int,int> P;
//vector<pair<int,int>> ::iterator iter;
//
//map<ll,int>mp;
//map<ll,int>::iterator p; const int N = 500000 + 10; int n; typedef struct C {
LL sum;
int id;
}; C c[N]; void clear() {
memset(c,0,sizeof(c));
} int lowbit(int x) {
return x&(-x);
}
//设原始矩阵为a,将a[i]加上val时对c所做的改动
void update(int i, int val) {
int j = i;
while (i <= n) {
c[i].id += val;
c[i].sum += j;
i += lowbit(i);
}
} int get_sumid(int i) {
int sum = 0;
while(i > 0) {
sum += c[i].id;
i -= lowbit(i);
}
return sum;
} //求前i项元素的和
LL get_sum(int i) {
LL sum=0;
while (i > 0) {
sum += c[i].sum;
i -= lowbit(i);
}
return sum;
} int main() {
while(scanf("%d",&n) == 1) {
clear();
LL ans = 0;
for(int i=1;i<=n;i++) {
int x;
scanf("%d",&x);
update(x,1);
LL ans1 = i - get_sumid(x);//i代表当前已经插入的个数,ge_sum(aa[i])代表比aa[i]小的数个数,减去即为大的个数,即逆序数
if(ans1 != 0) {
LL ans2 = get_sum(n) - (1LL) * get_sum(x);
ans += ans1 * x + ans2;
}
}
printf("%I64d\n",ans);
}
return 0;
} /*
4
1 3 2 4 5
1 5 3 2 4 5
5 4 3 2 1 7
3 4 5 1 2 7 6 6
2 1 6 5 4 3 7
4 3 6 5 2 1 7 ans:
5
29
60
46
57
69
*/
HDU2838 Cow Sorting 树状数组 区间求和加逆序数的应用的更多相关文章
- hdu 1754 I Hate It(树状数组区间求最值)2007省赛集训队练习赛(6)_linle专场
题意: 输入一行数字,查询第i个数到第j个数之间的最大值.可以修改其中的某个数的值. 输入: 包含多组输入数据. 每组输入首行两个整数n,m.表示共有n个数,m次操作. 接下来一行包含n个整数. 接下 ...
- hdu 2838 Cow Sorting 树状数组求所有比x小的数的个数
Cow Sorting Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- hdu 2838 Cow Sorting (树状数组)
Cow Sorting Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- LG5200 「USACO2019JAN」Sleepy Cow Sorting 树状数组
\(\mathrm{Sleepy Cow Sorting}\) 问题描述 LG5200 题解 树状数组. 设\(c[i]\)代表\([1,i]\)中归位数. 显然最终的目的是将整个序列排序为一个上升序 ...
- HDU3874 /HDU3333 树状数组 区间求不重复数和
Necklace Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- HDU Cow Sorting (树状数组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2838 Cow Sorting Problem Description Sherlock's N (1 ...
- HDU 6318 Swaps and Inversions 思路很巧妙!!!(转换为树状数组或者归并求解逆序数)
Swaps and Inversions Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) E. Cards Sorting 树状数组
E. Cards Sorting time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
- hdu 4638 树状数组 区间内连续区间的个数(尽可能长)
Group Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
随机推荐
- Jdk 和 Tomcat的 安装。
1.再分发服务器上下载JDK,然后利用xftp上传到聚石塔等 2. 解压: tar -zxvf jdk-8u121-linux-x64.tar.gz 3.配置环境变量: export JAVA_HOM ...
- Python SGMLParser 的1个BUG??
首先说一下,我用的是python 2.7,刚好在学Python,今天想去爬点图片当壁纸,但是当我用 SGMLParser 做 <img> 标签解析的时候,发现我想要的那部分根本没获取到,我 ...
- centos7 配置ftp访问
vsftp安装 创建用户 并限定用户在自己的目录 1.查看是否已经安装了vsftpd vsftpd -version 2.安装vsftpd(CentOS7) yum install -y vsftpd ...
- C语言:九九乘法表打印
题目: 要求:用“,”分隔算式,用“:”做一行的结尾. 另外1*1=1:这个算式是程序的第一行,前面没有空行. 文字版如下: 输入格式: 无 输出格式: 1*1=1; 2*1=2,2*2=4; 3*1 ...
- 【LOJ】#2340. 「WC2018」州区划分
题解 学习一个全世界人都会只有我不会的东西 子集变换! 难道我要把这题当板子讲?等等这题好像是板...WC出板题好刺激啊= = 假装我们都做过HAOI2015的FMT题,我们都知道一些FMT怎么解决或 ...
- 使用setsid替代nohup
使用setsid替代nohup 使用 nohup 执行sudo -e时会有问题的.
- caffe for python
导言 本教程中,我们将会利用Caffe官方提供的深度模型——CaffeNet(该模型是基于Krizhevsky等人的模型的)来演示图像识别与分类.我们将分别用CPU和GPU来进行演示,并对比其性能.然 ...
- Wannafly挑战赛9 D - 造一造
链接:https://www.nowcoder.com/acm/contest/71/D来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言52428 ...
- JAVAEE——SSH项目实战06:统计信息管理、Spring注解开发和EasyUI
作者: kent鹏 转载请注明出处: http://www.cnblogs.com/xieyupeng/p/7190925.html 一.统计信息管理 二.Spring注解开发 1.service ...
- 将已有的项目提交到GitHub
1.目的: 将已有的项目提交到GitHub 2.准备工作 2.1 此教程建立在对git有初步的理解上 2.2 此教程之前需准备工作 a.熟悉git的一些基本命令和原理. b.已注册有GitHub账号. ...