mot1ve @ 2023-01-07 16:38:58
nlogn,5e5的数据不至于600ms吧
//先把原数组离散化unique+lower_bound
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long ans;
int a[1000010],b[1000010];
struct node{
int l,r,sum;
}tree[4000010];
void build(int p,int l,int r)
{
tree[p].l=l;
tree[p].r=r;
if(l==r)
return;
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
}
void update(int p,int c)//单点修改,把c这个数的位置++
{
if(tree[p].l==tree[p].r)
{
tree[p].sum++;
return ;
}
int mid=(tree[p].l+tree[p].r)>>1;
if(c<=mid)
update(p<<1,c);
else update(p<<1|1,c);
tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
}
int query(int p,int l,int r)//区间查询
{
if(l<=tree[p].l&&tree[p].r<=r)
{
return tree[p].sum;
}
int mid=(tree[p].l+tree[p].r)>>1;
int res=0;
if(l<=mid)
res+=query(p<<1,l,r);
if(r>mid)
res+=query(p<<1|1,l,r);
return res;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
m=unique(b+1,b+1+n)-b-1;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(b+1,b+1+m,a[i])-b;
}
build(1,1,m);
for(int i=1;i<=n;i++)
{
ans+=query(1,a[i]+1,m);
update(1,a[i]);
}
cout<<ans;
return 0;
}
by Usada_Pekora @ 2023-01-07 16:50:34
@Herkaii 正常。
by Usada_Pekora @ 2023-01-07 16:57:33
@Herkaii 可以通过对线段树本身的修改改到 500ms,你这个 tree[p].l,r
都是没必要存的,因为你每次还是重新算了一次 mid
,所以直接传参数就好了。
然后修改不需要 pushup
,因为你实际上是对路径上经过的所有 p
进行 ++
操作。
by mot1ve @ 2023-01-07 17:00:01
@Zyingyzzz thx
by Killer_joke @ 2023-01-07 17:18:09
您的初始化稍微有点慢 占用了大约一半的耗时