BZOJ4889 & Luogu 3759: [TJOI2017] The Industrious Librarian - Problem Solving

https://www.lydsy.com/JudgeOnline/problem.php?id=4889

https://www.luogu.org/problemnew/show/P3759

Garrytown University has an Imperial Library, and Xiaodou is a librarian in the library's reading room. His task is to arrange the books in an orderly manner, so unordered books make him bored, and two books out of order make Xiaodou bored by the sum of the pages of the two books. Now there are n books that are out of order, and the order of the books will change every day for the next m days due to readers' reading. Because Xiaodou is required to organize books at least once in the next m days. Xiaodou wanted to know, if he didn't tidy up the day before, what was his boredom on the ith day, so that he could choose the day with the least boredom to tidy up.

At first I thought the solution was very naive, but later I found out that I was too naive.

It looks like checking the reverse order pair. For the exchange of l and r, the change of its contribution is only related to the intervals [l+1, r-1]. It can be turned into a query of how many of these intervals satisfy the relationship between l and r. r constitutes a reverse order pair.

This can obviously be done by the chairman tree.

However, then you need to swap these two numbers... emmm the chairman tree to be modified.

In fact, it is a tree array with a dynamic open-point line segment tree (because the essence is almost the same as the chairman tree.)

All that's left is to code.

(Note the effect of modulo on constants.)

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e4+5;
const int p=1e9+7;
inline int read(){
    int X=0,w=0;char ch=0;
    while(ch<'0'||ch>'9'){w|=ch=='-';ch=getchar();}
    while(ch>='0'&&ch<='9')X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct tree{
    int l,r;
    ll v,c;
}tr[N*200];
int rt[N],pool,n,m;
ll ans,a[N],v[N],b[N],cnt[N];
inline int lowbit(int x){return x&(-x);}
inline void add(int x,int y){
    for(int i=x;i<=n;i+=lowbit(i))b[i]+=y,cnt[i]++;
}
inline ll qry_val(int x){
    ll res=0;
    for(int i=x;i;i-=lowbit(i))res+=b[i];
    return res;
}
inline ll qry_cnt(int x){
    ll res=0;
    for(int i=x;i;i-=lowbit(i))res+=cnt[i];
    return res;
}
inline void insert(int &x,int l,int r,int pos,int v,int w){
    if(!x)x=++pool;
    tr[x].v+=v;tr[x].c+=w;
    if(l==r)return;
    int mid=(l+r)>>1;
    if(pos<=mid)insert(tr[x].l,l,mid,pos,v,w);
    else insert(tr[x].r,mid+1,r,pos,v,w);
}
inline void ins(int i,int x,int y,int w){
    for(;i<=n;i+=lowbit(i))insert(rt[i],1,n,x,y,w);
}
inline ll sqv(int x,int l,int r,int l1,int r1){
    if(r<l1||r1<l)return 0;
    if(l1<=l&&r<=r1)return tr[x].v;
    int mid=(l+r)>>1;
    return sqv(tr[x].l,l,mid,l1,r1)+sqv(tr[x].r,mid+1,r,l1,r1);
}
inline ll sqc(int x,int l,int r,int l1,int r1){
    if(r<l1||r1<l)return 0;
    if(l1<=l&&r<=r1)return tr[x].c;
    int mid=(l+r)>>1;
    return sqc(tr[x].l,l,mid,l1,r1)+sqc(tr[x].r,mid+1,r,l1,r1);
}
inline ll query_val(int l,int r,int l1,int r1){
    if(l>r||l1>r1)return 0;
    l--;ll res=0;
    for(int i=r;i;i-=lowbit(i))res=(res+sqv(rt[i],1,n,l1,r1))%p;
    for(int i=l;i;i-=lowbit(i))res=(res-sqv(rt[i],1,n,l1,r1))%p;
    return (res+p)%p;
}
inline ll query_cnt(int l,int r,int l1,int r1){
    if(l>r||l1>r1)return 0;
    l--;ll res=0;
    for(int i=r;i;i-=lowbit(i))res=(res+sqc(rt[i],1,n,l1,r1))%p;
    for(int i=l;i;i-=lowbit(i))res=(res-sqc(rt[i],1,n,l1,r1))%p;
    return (res+p)%p;
}
inline void check(ll &x){
    while(x>=p)x-=p;
    while(x<0)x+=p;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++){
        a[i]=read(),v[i]=read();
        ins(i,a[i],v[i],1);
    }
    for(int i=n;i>=1;i--){
        add(a[i],v[i]);
        ans=(ans+qry_val(a[i]-1)+qry_cnt(a[i]-1)*v[i])%p;
    }
    for(int i=1;i<=m;i++){
        int l=read(),r=read();
        if(l==r){printf("%lld\n",ans);continue;}
        if(l>r)swap(l,r);
        ans =ans+query_val(l+ 1,r-1,1,a[r]-1 ) ; check ( ans ) ;
        ans =ans+query_cnt(l+ 1 ,r - 1,1 , a[r] -1 )* v [r];check(ans);
        ans =ans-query_val(l+ 1 ,r - 1 ,a[r]+ 1 ,n);check(ans);
        ans =ans-query_cnt(l+ 1 ,r - 1 ,a[r]+ 1 ,n)* v[r];check(ans);
        ans =ans+query_val(l+ 1 ,r - 1 ,a[l]+ 1 ,n);check(ans);
        ans =ans+query_cnt(l+ 1 ,r - 1 ,a[l]+ 1 ,n)* v[l];check(ans);
        ans =ans-query_val(l+ 1 ,r - 1,1 , a[ l ] -1 );check(ans);
        ans =ans-query_cnt(l+ 1 ,r - 1,1 , a[ l ] -1 )* v[l];check(ans);
        if (a[l]>a[r])ans-=v[l]+ v[r];
        else ans+=v[l]+ v[r];
        check(years);
        ins(l,a[l],-v[l],-1);ins(r,a[r],-v[r],-1);
        swap(a[l],a[r]);swap(v[l],v[r]);
        ins(l,a[l],v[l],1);ins(r,a[r],v[r],1);
        printf("%lld\n",ans);
    }
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+ Author of this article: luyouqi233. +

+Welcome to my blog: http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325083705&siteId=291194637