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,我们能够进行这么一种操作:把第一个数移到最 ...
随机推荐
- C# .NET 如何修改代码字体
工具-选项-字体和颜色
- 使用adb在电脑和手机间传文件
首先须要root手机. 然后,"Win + R",打开cmd窗体.以下以copy d:\1.txt到/system/文件夹为例说明. adb push source(localpa ...
- C++ - 使用copy函数打印容器(container)元素
使用copy函数打印容器(container)元素 本文地址: http://blog.csdn.net/caroline_wendy C++能够使用copy函数输出容器(container)中的元素 ...
- java 翻页工具类
Pagination类 package com.paic.bics.core.mybatis.page; import java.util.List; @SuppressWarnings(" ...
- 另类创业招聘(REV#2)
项目一 项目名:苏格拉底网 项目性质:人才測评为主.辅助以简易人才招聘功能的小众功能站点.项目使用了自主研发的人才測评算法以及人格分类模型(与MBTI非常相似). 项目相关网址:sugeladi.ne ...
- cocos2dx 在android平台打开文件问题
我们有一个项目是基于cocos2dx + lua,在网络部分用到了protobuf, 在初始化protobuf的时候须要读取本地文件,用lua的io.open读取文件在windows,ios上 ...
- SDK Manager配置
改Host的都是扯淡,现在不好使了.. 还是使用东软的国内镜像好使,打开SDK Manager Tools - Options Http proxy Server: mirrors.neusoft. ...
- android简易双屏支持【转】
本文转载自:http://blog.csdn.net/sfrysh/article/details/7463339 抱歉,之前说xorg的exa更新的时候恐怕一直不会更新了,没有做xorg开发了.转向 ...
- YTU 2543: 数字整除
2543: 数字整除 时间限制: 1 Sec 内存限制: 128 MB 提交: 33 解决: 8 题目描述 定理:把一个至少两位的正整数的个位数字去掉,再从余下的数中减去个位数的5倍.当且仅当差是 ...
- CentOS常用基础命令大全
这篇文章主要介绍了CentOS常用基础命令大全,学习centos的朋友需要掌握的知识,需要的朋友可以参考下 1.关机 (系统的关机.重启以及登出 ) 的命令shutdown -h now 关闭系统(1 ...