P1637 三元上升子序列
阿新 • • 發佈:2018-02-17
輸入輸出 names ac代碼 span mes != || while bad
題目描述
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 三元上升子序列