【问题描述】
给定N,以及A1,A2,……AN,求所有的数对(i,j)同时满足:
(1) i<j
(2) 2Ai>Aj
【输入文件】
输入文件 inv.in第一行N
接下来N行,每行一个整数,第i行的整数为Ai
【输出文件】
输出文件inv.out包含一行一个整数,表示满足条件的数对的个数
【输入样例】
3
4 6 8
【输出样例】
2
【样例说明】
数对为(1,2),(2,3)
【数据规模】
N≤100000
1≤Ai≤10N,且所有Ai两两不同
30%数据N≤1000
50%数据N≤10000
注意:
输出的大小可能会超过32位整数
题解:线段树逆序对模板,数据大,离散。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define lsn x+x
#define rsn x+x+1
#define lss l,mid
#define rss mid+1,r
using namespace std;
typedef long long ll;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
void write(ll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int n,m,a[N],b[N],num[2*N],t[8*N];
ll ans=0;
inline void init()
{
n=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
b[i]=2*a[i];
num[i]=a[i];
num[n+i]=b[i];
}
sort(num+1,num+1+n+n);
m=unique(num+1,num+1+n+n)-num-1;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(num+1,num+1+m,a[i])-num;
b[i]=lower_bound(num+1,num+1+m,b[i])-num;
}
}
void change(int x,int l,int r,int p)
{
if(l==r&&l==p)
{
t[x]++;
return;
}
int mid=(l+r)/2;
if(p<=mid) change(lsn,lss,p);
else change(rsn,rss,p);
t[x]=t[lsn]+t[rsn];
}
int find(int x,int l,int r,int s,int e)
{
if(l==s&&r==e) return t[x];
int mid=(l+r)/2;
if(e<=mid) return find(lsn,lss,s,e);
else if(s>mid) return find(rsn,rss,s,e);
else return find(lsn,lss,s,mid)+find(rsn,rss,mid+1,e);
}
int main()
{
freopen("inv.in","r",stdin);
freopen("inv.out","w",stdout);
memset(t,0,sizeof(t));
init();
for(int i=1;i<=n;i++)
{
ans+=find(1,1,m,a[i]+1,m);
change(1,1,m,b[i]);
}
write(ans);
return 0;
}