大佬们,为什么这题用线段树做错了QAQ(已经离散化)

P1908 逆序对

theHermit @ 2020-09-26 22:04:30

#include<bits/stdc++.h>
#define For(i,m,n) for(register int i=m;i<n;i++)
#define rFor(i,m,n) for(register int i=m;i>n;i--)
#define r(a) read(a)
#define rr(a,b) read(a),read(b)
#define rrr(a,b,c) read(a),read(b),read(c)
using namespace std;
typedef long long ll;
template <class T>
inline void read(T &x)
{
    x=0;
    T f=1;
    char ch=getchar();
    while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    x=x*f;
}
const int MAXN=1000100;
const int INF=214783647;
ll n,m,a[MAXN],ans[MAXN<<2],add_tag[MAXN<<2];
ll sum[MAXN<<2];
ll bucket[MAXN];
ll smaller[MAXN],bigger[MAXN];
ll res=0;
struct state{
    ll val;
    ll ord;
}in[MAXN];

void show()
{
    For(i,0,15){
        printf("tree[%d] = %d\n",i,ans[i]);
    }
    cout<<endl;
}

inline int ls(int x)
{
    return x<<1;
}

inline int rs(int x)
{
    return x<<1|1;
}

ll query(ll L,ll R,ll lo,ll hi,ll node)
{
    if(L<=lo&&hi<=R)return sum[node];//如果这就是我们想要的区间
    ll mid=(lo+hi)>>1;
    ll res=0;
    //res是根据我们父节点相应的规则,取得不同的值
    if(L<=mid)res+=query(L,R,lo,mid,ls(node));//这里可能要改
    if(R>mid) res+=query(L,R,mid+1,hi,rs(node));
    return res;
}

inline void push_up(int node)
{
    sum[node]=sum[ls(node)]+sum[rs(node)];
}

void build(int node,int lo,int hi)
{
    if(lo==hi){
        return;
    }//这个是只有输入数据的数组,才会赋值给输入数据的节点层
    int mid=(lo+hi)>>1;
    build(ls(node),lo,mid);
    build(rs(node),mid+1,hi);
    push_up(node);//根据题目操作要改,这里是根据输入数据,构建线段树输入数据的爸爸
}

void updateKmax(ll pos,ll lo,ll hi,ll node)
{
    if(lo==pos&&hi==pos){
        sum[node]++;
        return;
    }

    ll mid=(lo+hi)>>1;
    if(pos<=mid)   updateKmax(pos,lo,mid,ls(node));
    else if(pos>mid)    updateKmax(pos,mid+1,hi,rs(node));
    push_up(node);
}

bool cmp(state &n1,state &n2)
{
    if(n1.val!=n2.val)  return n1.val<n2.val;
    else                return n1.ord<n2.ord;
}

void input()
{
    r(n);
    For(i,1,n+1){
        r(in[i].val);
        in[i].ord=i;
    }
    sort(in+1,in+1+n,cmp);//从小到大排列权值
    int cnt=0;
    //离散化,重新排列权值
    For(i,1,n+1){
        if(in[i].val>in[i-1].val)   cnt++;
        bucket[in[i].ord]=cnt;
    }
    build(1,1,n);

  //求出比当前i大的bigger[i]个数字                        
    rFor(i,n,0){
        if(bucket[i]<n)    bigger[i]=query(bucket[i]+1,n,1,n,1);
        updateKmax(bucket[i],1,n,1);
    }
    For(i,1,n){
        res+=(n-i-bigger[i]);
    }
}

int main()
{
    input();
    cout<<res;

    return 0;
}

by theHermit @ 2020-09-26 22:11:45

我明白了!!!!!

最后不能直接res+=(n-i-bigger[i])

因为有重复的数QAQ

我是琪露诺(雾


by theHermit @ 2020-09-26 22:19:53

更改后应为:

    For(i,1,n){
        int num=--mp[bucket[in[i].ord]];
        res+=(n-i-num-bigger[i]);
    }

|