码迷,mamicode.com
首页 > 其他好文 > 详细

P1637 三元上升子序列

时间:2018-02-17 10:27:56      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:100%   生成   body   size   整数   add   print   不能   gpo   

 题目描述

Erwin最近对一种叫"thair"的东西巨感兴趣。。。

在含有n个整数的序列a1,a2......an中,

三个数被称作"thair"当且仅当i<j<k且ai<aj<ak

求一个序列中"thair"的个数。

输入输出格式

输入格式:

开始一个正整数n,

以后n个数a1~an。

 

输出格式:

"thair"的个数

 

输入输出样例

输入样例#1: 复制
4
2 1 3 4
输出样例#1: 复制
2
输入样例#2: 复制
5
1 2 2 3 4
输出样例#2: 复制
7

说明

对样例2的说明:

7个"thair"分别是

1 2 3 1 2 4 1 2 3 1 2 4 1 3 4 2 3 4 2 3 4 约定 30%的数据n<=100

60%的数据n<=2000

100%的数据n<=30000

大数据随机生成

0<=a[i]<=maxlongint

 

其实就是求逆序对,设ans1为之前比他小的数的个数,ans2为大的个数,显然ans+=ans1*ans2.

我们看到这数据规模,不能用桶,得离散化一下……然后常规操作。

AC代码如下:

 

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=30000+5;
struct p{
    int id,num;
    bool operator < (const p &aa) const{
    return num<aa.num;}
}a[N];
int ans1[N],ans2[N],n,c[N],pos[N],now;
long long ans;
int sum(int x)
{
    int res=0;
    while(x>0) res+=c[x],x-=(x&-x);
    return res;
}
void add(int x)
{
    while(x<=n) c[x]++,x+=(x&-x);
    return; 
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&a[i].num),a[i].id=i;
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++)
     pos[a[i].id]=((a[i].num!=a[i-1].num)||i==1)?i:pos[a[i-1].id];
    for(int i=1;i<=n;i++)
    now=pos[i],ans1[i]=sum(now-1),add(now);
    fill(c+1,c+n+1,0);
    for(int i=n;i>0;i--)
    now=pos[i],ans2[i]=sum(n-now),add(n-now+1);
    for(int i=1;i<=n;i++)
    ans+=ans1[i]*ans2[i];
    printf("%lld",ans);
    return 0;
}

P1637 三元上升子序列

标签:100%   生成   body   size   整数   add   print   不能   gpo   

原文地址:https://www.cnblogs.com/Alex-leaves/p/8451417.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!