洛谷P3759 - [TJOI2017]不勤劳的图书管理员

Portal

Description

给出一个\(1..n(n\leq5\times10^4)\)的排列\(\{a_n\}\)和数列\(\{w_n\}(w_i\leq10^5)\),进行\(m(m\leq5\times10^4)\)次操作:
交换\(a_{p_1},a_{p_2}\),并求\(\sum_{i=1}^n \sum_{j=i+1}^n [a_i>a_j](w_{a_i}+w_{a_j})\)

Solution

树套树/CDQ分治,想锻炼一下代码能力所以写了树套树。
首先这是一个求逆序对的问题,那么我们考虑交换\(a_{p_1},a_{p_2}\)对答案有什么影响。易知只有\(i\in[p_1+1,p_2-1]\)对答案造成影响:
\(a_i,那么答案减\(a_i+a_{p_1}\);若\(a_i>a_{p_1}\),那么答案加\(a_i+a_{p_1}\)
\(a_i,那么答案加\(a_i+a_{p_2}\);若\(a_i>a_{p_2}\),那么答案减\(a_i+a_{p_2}\)
那么求出\(\{c_1,s_1,c_2,s_2\}\)分别表示区间\([p_1+1,p_2-1]\)内小于/大于\(x\)\(i\)的个数/\(w_i\)的和,然后就可以根据上两行计算答案的变化。而这可以用树套树来做。

时间复杂度\(O(mlog^2n)\)

Code

//[TJOI2017]不勤劳的图书管理员
#include 
#include 
using std::swap;
typedef long long lint;
inline char gc()
{
    static char now[1<<16],*s,*t;
    if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
    return *s++;
}
inline int read()
{
    int x=0; char ch=gc();
    while(ch<'0'||'9'0)+(ch[p][1]>0);
        if(chCnt==0) {rt=0; return p;}
        if(chCnt==1) {rt=ch[p][ch[p][1]>0],fa[rt]=0; return p;}
        int q=ch[p][0]; while(ch[q][1]) q=ch[q][1];
        splay(rt,q);
        fa[ch[q][1]=ch[p][1]]=q;
        fa[p]=ch[p][0]=ch[p][1]=0;
        update(q);
        return p;
    }
    inline void change(int &rt,int x1,int x2)
    {
        int p=del(rt,x1); if(!p) p=++cnt;
        fa[p]=ch[p][0]=ch[p][1]=0,siz[p]=1;
        val[p]=x2,sum[p]=w[x2];
        ins(rt,p);
    }
    info query(int rt,int x)
    {
        int c1=0,s1=0;
        for(int p=rt;p;p=ch[p][val[p]>1;
        if(in(L0,mid,p1,p2)) change(Ls,L0,mid,p1,p2);
        if(in(mid+1,R0,p1,p2)) change(Rs,mid+1,R0,p1,p2);
    }
    int optL,optR;
    info query(int p,int L0,int R0,int x)
    {
        if(optL<=L0&&R0<=optR) return inTr::query(rt[p],x);
        int mid=L0+R0>>1; info res=info(0,0,0,0);
        if(optL<=mid) res=res+query(Ls,L0,mid,x);
        if(midp2) swap(p1,p2); else if(p1==p2) {printf("%d\n",ans); continue;}
        int x=a[p1],y=a[p2];
        info r1=query(p1+1,p2-1,x),r2=query(p1+1,p2-1,y);
        ans-=((lint)r1.c1*w[x]%P+r1.s1)%P; ans=(ans+P)%P;
        ans+=((lint)r1.c2*w[x]%P+r1.s2)%P; ans=ans%P;
        ans+=((lint)r2.c1*w[y]%P+r2.s1)%P; ans=ans%P;
        ans-=((lint)r2.c2*w[y]%P+r2.s2)%P; ans=(ans+P)%P;
        if(x

转载于:https://www.cnblogs.com/VisJiao/p/LgP3759.html

你可能感兴趣的:(洛谷P3759 - [TJOI2017]不勤劳的图书管理员)