训练日记-16
来源:互联网 发布:做淘宝电脑配置 编辑:程序博客网 时间:2024/06/11 05:57
今天首先把树状数组中求逆序数的算法看了一下,然后看了一下线段树的课件。
逆序数的基本框架如下:
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
int b[500005], c[500005];
int n;
struct node
{
int num, id;
}a[500005];
bool cmp(node a, node b)
{
return a.num < b.num;
}
void update(int i, int x)
{
while(i <= n)
{
c[i] += x;
i += i&(-i);
}
}
int sum(int i)
{
int sum = 0;
while(i > 0)
{
sum += c[i];
i -= i&(-i);
}
return sum;
}
int main()
{
int i;
long long ans;
while(scanf("%d", &n), n)
{
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));
for(i = 1; i <= n; i++)
{
scanf("%d", &a[i].num); //输入数值num
a[i].id = i; //记录序号id
}
///开始离散化
sort(a+1, a+n+1, cmp); //先排序
/*因为a[1].num是最小的,id是它的位置,所以b[a[1].id]=1最小,
最小的数变成1,第二小的变成2,如此类推从而达到离散化*/
b[a[1].id] = 1;
for(i = 2; i <= n; i++)
{
if(a[i].num != a[i-1].num)
b[a[i].id] = i;
else b[a[i].id] = b[a[i-1].id];
}
///离散化完毕
ans = 0;
for(i = 1; i <= n; i++)
{
update(b[i], 1);
//这里很巧妙,每一次更新后,判断此数比左边的数小的数有多少
ans += (sum(n)-sum(b[i]));
}
//从而求到:右边的数比左边的数大的个数的总和
printf("%I64d\n", ans);
//这里必须注意一下,数据比较大的话不用64位很容易出错,所以最好还是用64位输出
}
return 0;
}
看到训练三一直关着,最近一直在看课件跟例题,我一直纳闷这么多天了训练三为什么一直关着。。。今晚上问了一下别人才知道还有一个开着的训练三。。。 很郁闷,很绝望。 然后今晚上的时间就先刷了两道A的最多的两道题,一道是二维树状数组问题,另一道是刚看的求逆序数的问题。
从明天开始要正式开始刷题了!
继续加油!
- 训练日记-16
- 训练日记
- 训练日记
- 训练日记
- 训练日记
- 训练日记
- 训练日记
- 训练日记
- 训练日记
- 训练日记
- 训练日记
- 训练日记
- 训练日记
- 训练日记
- 训练日记
- 训练日记 2.10 - 4.7
- 【训练日记】20161024
- 【训练日记】20161028
- 洛谷 P1007 独木桥
- 【JZOJ5330】【NOIP提高组模拟】密码(库默尔定理、数位DP)
- Java基础部分(一)
- nativescript 工程如何clean?
- 单例模式的测试
- 训练日记-16
- 环境变量与Jdk配置相关
- intellij idea 显示打开文件路径按钮
- java栈、堆、方法区详解
- 使用Qt+OpenGL创建球体+简单交互
- window对象下open、close、opener函数的使用
- QUIC和TCP--为什么多线程下载比单线程快
- 一行或者多行垂直居中问题
- Linux下设置mysql和tomcat开机启动