LG1908LG1908

其实就是求逆序对。而逆序对就是求每一个数前面有多少个比它大,则考虑权值线段树。
什么是权值线段树? 就是以数的大小作区间的线段树。
然而,此题数据范围太大,所以需要一个小小的预处理操作:
例:2 8 0 3 2,我们可以排个序(要保留原版):0 2 2 3 8
去重:0 2 3 8,编号为:1,2,3,4。再对应回去:2 4 1 3 2
(要开个结构体,记录原位置)
一系列操作得: $1<=A_i<=n​$
好了,现在可以构造了。(值都为0)


查询逆序对,先从前向后依次查询,记录总和,查询后加入线段树并回溯

献上丑陋的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

using namespace std;
typedef long long LL;
inline int ()
{
int x=0,flag=1;
char ch=getchar();
while((ch<'0' || ch>'9') && ch!='-') ch=getchar();
if(ch=='-') flag=-1,ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x*flag;
}
inline LL rdl()
{
LL x=0,flag=1;
char ch=getchar();
while((ch<'0' || ch>'9') && ch!='-') ch=getchar();
if(ch=='-') flag=-1,ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x*flag;
}
const int N=5e5+50;
const int TR=N<<2;
struct tree{
int l,r,k;
}t[TR];
inline int ls(int x)//左儿子
{
return x<<1;
}
inline int rs(int x)//右儿子
{
return x<<1|1;
}
struct no{
int x,i;
}cop[N];
bool comp(no x,no y)
{
return x.x<y.x;
}
inline void build(int now,int l,int r)//建树
{
t[now].l=l;
t[now].r=r;
t[now].k=0;
if(l==r)
return ;
int mid=(l+r)>>1;
build(ls(now),l,mid);
build(rs(now),mid+1,r);
return ;
}
inline void up(int now)//回溯
{
t[now].k=t[rs(now)].k+t[ls(now)].k;
}
inline LL src(int now,int x)//搜索
{
int l=t[now].l,r=t[now].r;
LL sum=0;
int mid=(l+r)>>1;
if(l==r)
return (LL)t[now].k;
if(x<=mid) sum+=(LL)t[rs(now)].k+src(ls(now),x);//若在左儿子中,右儿子一定比它大
else sum+=src(rs(now),x);//搜索右儿子
return sum;
}
inline void upate(int now,int x)//加入
{
int l=t[now].l,r=t[now].r;
int mid=(l+r)>>1;
if(l==r)
{
t[now].k++;//统计个数
return ;
}
if(x<=mid) upate(ls(now),x);
else upate(rs(now),x);
up(now);
}
int n;
LL a[N],k[N],tot=0,ans=0;//开long long防爆
int main()
{
n=rd();
for(int i=1;i<=n;i++) a[i]=rdl(),cop[i].x=a[i],cop[i].i=i;
sort(cop+1,cop+n+1,comp);
for(int i=1;i<=n;i++)
{
if(cop[i].x!=cop[i-1].x || i==1)
k[++tot]=cop[i].x;
a[cop[i].i]=tot;
}//预处理
build(1,1,n);
for(int i=1;i<=n;i++)
{
ans+=src(1,a[i]+1);//大于a的个数=大于等于a+1的个数
upate(1,a[i]);//更新
}
cout<<ans<<endl;
return 0;
}