Daniel_yao @ 2022-09-30 08:34:56
RT
#include <bits/stdc++.h>
#define int long long
#define H 19260817
#define rint register int
#define For(i,l,r) for(rint i=l;i<=r;++i)
#define FOR(i,r,l) for(rint i=r;i>=l;--i)
#define MOD 1000003
#define mod 1000000007
using namespace std;
inline int read() {
rint 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<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
void print(int x){
if(x<0){putchar('-');x=-x;}
if(x>9){print(x/10);putchar(x%10+'0');}
else putchar(x+'0');
return;
}
const int N = 500010 * log(1e9);
struct Node {
int ls, rs;
int l, r;
int num;
}t[N << 2];
int n = read(), a[N], ans, mx, idx = 1;
void pushup(int p) {
t[p].num = t[t[p].ls].num + t[t[p].rs].num;
}
void add(int p, int l, int r, int k) {
t[p].l = l, t[p].r = r;
if(l == r) {
t[p].num ++;
return ;
}
int mid = l + r >> 1;
if(k <= mid) {
if(!t[p].ls) t[p].ls = ++idx;
add(t[p].ls, l, mid, k);
} else {
if(!t[p].rs) t[p].rs = ++idx;
add(t[p].rs, mid + 1, r, k);
}
pushup(p);
}
int query(int p, int l, int r) {
if(p == 0) return 0;
if(l <= t[p].l && t[p].r <= r) {
return t[p].num;
}
int mid = t[p].l + t[p].r >> 1, ans = 0;
if(l <= mid) {
ans += query(t[p].ls, l, r);
}
if(r > mid) {
ans += query(t[p].rs, l, r);
}
return ans;
}
signed main() {
For(i,1,n) a[i] = read(), mx = max(mx, a[i]);
For(i,1,n) {
add(1, 1, n, a[i]);
ans += query(1, a[i] + 1, mx);
}
cout << ans << '\n';
return 0;
}
by panyanppyy @ 2022-09-30 09:25:51
@yzy001633 按题目给的大小开
by bamboo12345 @ 2022-09-30 16:11:59
@yzy001633 其实可以不用权值线段树的
by bamboo12345 @ 2022-09-30 16:12:54
@yzy001633 这个题目用权值线段树够呛,一般是要开
by Daniel_yao @ 2022-09-30 16:31:40
@bamboo123 谢了,我已经找到树状数组的写法了。
by HZHan @ 2022-11-13 21:26:16
权值线段树如果动态开点的话一般要怼上值域的30倍吧