权值线段树咋这么慢

P1908 逆序对

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

您的初始化稍微有点慢 占用了大约一半的耗时


|