codeforces_459D_(线段树,离散化,求逆序数)
链接:http://codeforces.com/problemset/problem/459/D
3 seconds
256 megabytes
standard input
standard output
Parmida is a clever girl and she wants to participate in Olympiads this year. Of course she wants her partner to be clever too (although he's not)! Parmida has prepared the following test problem for Pashmak.
There is a sequence a that consists of n integers a1, a2, ..., an. Let's denote f(l, r, x) the number of indices k such that: l ≤ k ≤ r andak = x. His task is to calculate the number of pairs of indicies i, j (1 ≤ i < j ≤ n) such that f(1, i, ai) > f(j, n, aj).
Help Pashmak with the test.
The first line of the input contains an integer n (1 ≤ n ≤ 106). The second line contains n space-separated integers a1, a2, ..., an(1 ≤ ai ≤ 109).
Print a single integer — the answer to the problem.
7
1 2 1 1 2 2 1
8
3
1 1 1
1
5
1 2 3 4 5
0 题意:f(1,i,ai)表示(1,i)中等于ai的个数,f(j,n,aj)表示(j,n)中与aj相等的个数,求有多少对(i,j)。(特么,之前题意看错了,想了一上午没想明白,结果。。。)
思路:可以用数组fro统计每个位置(包括该位置)其前面有多少个与它相等的数,用beh数组统计每个位置其后有多少个与它相等的数。
样例:
7
1 2 1 1 2 2 1
fro:{1,1,2,3,2,3,4}
beh:{4,3,3,2,2,1,1} 问题就转化为求第一个序列相对第二个序列的逆序数(因为相当于i可以从fro中查看,j可以从beh中查看)
线段树求逆序数。。。
可以从前往后处理,也可以从后往前处理。
貌似从后往前更好理解。
从后往前处理,即,将beh依次插入树中,每插一个,查询其对应的fro的元素(1,fro[i]-1)区间也就是小于fro[i]的个数(查当前树中比fro[i]小的个数)
从前往后跟以上思路相反,插fro查beh(差当前树中比beh[i]大的个数)。
代码中第一次接触到离散化,以后可以借鉴。
此题还需多加理解。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<map>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
struct Node
{
int l,r;
int num;
} tree[<<]; int num[];
int fro[],beh[],sum[];
map<int,int> m1; void build(int l,int r,int rt)
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].num=;
if(tree[rt].l==tree[rt].r)
return;
int mid=(l+r)/;
build(lson);
build(rson);
} void update(int x,int l,int r,int rt)
{
tree[rt].num++;
if(tree[rt].l==tree[rt].r&&tree[rt].l==x)
return;
int mid=(l+r)/;
if(x<=mid)
update(x,lson);
else
update(x,rson);
} int query(int L,int R,int l,int r,int rt)
{
if(L>R)
return ;
if(L==l&&R==r)
return tree[rt].num;
int mid=(l+r)/;
if(R<mid)
return query(L,R,lson);
else if(L>mid)
return query(L,R,rson);
else
return query(L,mid,lson)+query(mid+,R,rson); }
int main()
{
int n;
scanf("%d",&n);
for(int i=; i<=n; i++)
scanf("%d",&num[i]);
int cnt=;
for(int i=; i<=n; i++) ///离散化,以后可以借鉴
{
if(!m1[num[i]])
m1[num[i]]=cnt++;
num[i]=m1[num[i]];
}
cnt=;
memset(sum,,sizeof(sum));
for(int i=; i<=n; i++)
{
sum[num[i]]++;
fro[i]=sum[num[i]];
cnt=max(cnt,fro[i]);
}
memset(sum,,sizeof(sum));
for(int i=n; i>=; i--)
{
sum[num[i]]++;
beh[i]=sum[num[i]];
}
build(,cnt,);
long long ans=;
for(int i=n; i>; i--)
{
update(beh[i],,cnt,);
//cout<<"**"<<endl;
ans+=query(,fro[i-]-,,cnt,);
//cout<<ans<<'*'<<endl;
}
printf("%I64d\n",ans);
return ;
}
codeforces_459D_(线段树,离散化,求逆序数)的更多相关文章
- 树状数组 && 线段树应用 -- 求逆序数
参考:算法学习(二)——树状数组求逆序数 .线段树或树状数组求逆序数(附例题) 应用树状数组 || 线段树求逆序数是一种很巧妙的技巧,这个技巧的关键在于如何把原来单纯的求区间和操作转换为 求小于等于a ...
- CF 61E 树状数组+离散化 求逆序数加强版 三个数逆序
http://codeforces.com/problemset/problem/61/E 题意是求 i<j<k && a[i]>a[j]>a[k] 的对数 会 ...
- HDU 1394 树状数组+离散化求逆序数
对于求逆序数问题,学会去利用树状数组进行转换求解方式,是很必要的. 一般来说我们求解逆序数,是在给定一串序列里,用循环的方式找到每一个数之前有多少个比它大的数,算法的时间复杂度为o(n2). 那么我们 ...
- POJ 2299 Ultra-QuickSort (树状数组+离散化 求逆序数)
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a seque ...
- BZOJ 3289 Mato的文件管理(莫队+离散化求逆序数)
3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MB Submit: 2171 Solved: 891 [Submit][Status][ ...
- poj1151 Atlanis 线段树+离散化求矩形面积的并
题目链接:http://poj.org/problem?id=1151 很经典的题目,网上有很多模板代码,自己理解了一天,然后很容易就敲出来了... 代码: #include<iostream& ...
- 线段树求逆序数方法 HDU1394&&POJ2299
为什么线段树能够求逆序数? 给一个简单的序列 9 5 3 他的逆序数是3 首先要求一个逆序数有两种方式:能够从头開始往后找比当前元素小的值,也能够从后往前找比当前元素大的值,有几个逆序数就是几. 线段 ...
- [CF 351B]Jeff and Furik[归并排序求逆序数]
题意: 两人游戏, J先走. 给出一个1~n的排列, J选择一对相邻数[题意!!~囧], 交换. F接着走, 扔一硬币, 若正面朝上, 随机选择一对降序排列的相邻数, 交换. 若反面朝上, 随机选择一 ...
- HDU 1394 Minimum Inversion Number (线段树 单点更新 求逆序数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给你一个n个数的序列,当中组成的数仅仅有0-n,我们能够进行这么一种操作:把第一个数移到最 ...
随机推荐
- FaceBook开源库Fresco
讨论学习使用 关于 Fresco Fresco 是一个强大的图片载入组件. Fresco 中设计有一个叫做 image pipeline 的模块.它负责从网络.从本地文件系统.本地资源载入图片. 为了 ...
- make常见报错原因分析
1 No rule to make target ‘xxx’ 原因一般是'xxx'文件不存在,首先应该去相应的目录检查文件是否存在.
- python any and all function
1 any 如果iterable object至少有一个元素是true的时候,返回为true.空的iterable object返回为false. 2 all 如果iterable object中的每 ...
- PNG vs. GIF vs. JPEG vs. SVG - When best to use?
image - PNG vs. GIF vs. JPEG vs. SVG - When best to use? - Stack Overflow https://stackoverflow.com/ ...
- 第二步:将LAD结果的属性值二(多)值化,投入计算模型
一文详解LDA主题模型 - 达观数据 - SegmentFault 思否 https://segmentfault.com/a/1190000012215533 SELECT COUNT(1) FRO ...
- Android合并两个APP的详细做法(掌握)
有时候因公司需求,要求合并两个APP 使用里面的功能. 平台:Studio 小白鼠:二维码扫描 和自己项目 详细步骤: /** * 1.将解压后的android/assets目录复制到项目中的mai ...
- Android原生音量控制【转】
本文转载自:http://blog.csdn.net/u013082948/article/details/65630085 本文主要涉及AudioService.还是基于5.1.1版本的代码. Au ...
- how to modify vs2017
https://docs.microsoft.com/en-us/visualstudio/install/modify-visual-studio 直接用everything搜索vs_install ...
- sql加一个%号是什么意思
sql%notfound 是异常SQL%ROWCOUNT SQL语句执行影响的行数SQL%FOUND SQL语句是否成功执行SQL%NOTFOUND SQL语句是否成功执行SQL%ISOPEN 游标是 ...
- luogu 3375 【模板】KMP字符串匹配
我太菜了 今天才学会kmp #include<iostream> #include<cstdio> #include<algorithm> #include< ...