CQOI2011-动态逆序对

QAQ这题就是个裸的树套树,但是你问我为什么一直T掉,那么就证明你脸黑QAQ。
统计:
区间[1,pos - 1]中 > a[pos]的
区间[pos - 1,n]中 < a[pos]的
这个可以用线段树套平衡树来解决。
当然也可以用树状数组套线段树解决。
然后常数大T了一次,加了快读之后+时限放宽就A掉了QAQ

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define Rep(i,n) for(int i = 1;i <= n;i ++)
#define RepD(i,n) for(int i = n;i;i --)
#define u t[x]
#define o t[y]

#define lc ch[0]
#define rc ch[1]
#define ulfc t[u.lc]
#define urtc t[u.rc]
#define tc ch[ty]
#define vc ch[!ty]

#define RT 1,1,n
#define mid (l + r >> 1)
#define lson x << 1,l,mid
#define rson x << 1 | 1,mid + 1,r

using namespace std;
const int N = 100005;
int tot,m,n,a[N],rt[N << 2],del[N],bit[N << 1],Rank[N];
struct Tree{int sz,ch[2],fix,val;void Set(int vl){val = vl,fix = rand(),sz = 1,ch[0] = ch[1] = 0;}}t[N * 40];
namespace Bit
{
    void Add(int tx){for(int x = tx;x <= n;x += x & -x)bit[x] ++;}
    long long Qry(int tx){long long s = 0;for(int x = tx;x;x -= x & -x)s += bit[x];return s;}
    long long Query(){long long now = 0;RepD(i,n)now += Qry(a[i]),Add(a[i]);return now;}
};
namespace Treap
{
    void Upd(int x){u.sz = ulfc.sz + urtc.sz + 1;}
    void Rot(int &x,bool ty){int y = u.tc;u.tc = o.vc,o.vc = x,Upd(x),Upd(x = y);}
    void Ins(int &x,int val)
    {
        if(!x){t[x = ++ tot].Set(val);return;}
        bool ty = val > u.val;
        Ins(u.tc,val);
        t[u.tc].fix > u.fix ? Rot(x,ty) : Upd(x);
    }
    void Del(int &x,int val)
    {
        if(u.val == val)
        {
            bool ty = urtc.fix > ulfc.fix;
            if(!u.tc){x = 0;u.sz = 0;return ;}
            Rot(x,ty),Del(u.vc,val);
        }
        else Del(u.ch[u.val < val],val);
        Upd(x);
    }
    long long Qry(int tx,int val,bool p = 0)
    {
        long long ans = 0;
        for(int x = tx;x;)u.val < val ? ans += ulfc.sz + 1,x = u.rc : x = u.lc;
        return !p ? ans : t[tx].sz - ans;
    }
};
void Ins(int x,int l,int r,int k)
{
    Treap :: Ins(rt[x],a[k]);
    if(l == r)return;
    k > mid ? Ins(rson,k) : Ins(lson,k);
}
void Del(int x,int l,int r,int k)
{
    Treap :: Del(rt[x],a[k]);
    if(l == r)return;
    k > mid ? Del(rson,k) : Del(lson,k);
}
long long QryD(int x,int l,int r,int ql,int qr,int k) // 小于k && j > i 的有几个 
{
    if(ql > qr)return 0;
    if(l >= ql && r <= qr)return Treap :: Qry(rt[x],a[k]);
    long long ans = 0;
    if(ql <= mid)ans += QryD(lson,ql,qr,k);
    if(mid < qr)ans += QryD(rson,ql,qr,k);
    return ans;
}
long long Qry(int x,int l,int r,int ql,int qr,int k)
{
    if(ql > qr)return 0;
    if(l >= ql && r <= qr)return Treap :: Qry(rt[x],a[k],1);//大于k && j < i 的有几个 
    long long ans = 0;
    if(ql <= mid)ans += Qry(lson,ql,qr,k);
    if(mid < qr)ans += Qry(rson,ql,qr,k);
    return ans;
}
int read()
{
    char ch = getchar();
    int x = 0;
    while(ch < '0' || ch > '9')ch = getchar();
    while(ch >= '0' && ch <= '9')x = 10 * x + ch - '0',ch = getchar();
    return x;
}
int main ()
{
    srand(23333);
// freopen("data.in","r",stdin);
// freopen("treap.txt","w",stdout);
    scanf("%d%d",&n,&m);
    Rep(i,n){a[i] = read();Ins(RT,i);Rank[a[i]] = i;}
    long long ans = Bit :: Query();
    Rep(i,m){
        int pos;
        //scanf("%d",&pos);
        pos = read();
        pos = Rank[pos];
        printf("%lld\n",ans);
        Del(RT,pos);
        ans -= Qry(RT,1,pos - 1,pos);
        ans -= QryD(RT,pos + 1,n,pos);
    }
    return 0;
}

你可能感兴趣的:(CQOI2011-动态逆序对)