[TJOI2017] 不勤勞的圖書管理員

題目描述


加里敦大學有個帝國圖書館,小豆是圖書館閱覽室的一個書籍管理員。他的任務是把書排成有序的,因此無序的書讓他產生厭煩,兩本亂序的書會讓小豆產生這兩本書頁數的和的厭煩度。如今有n本被打亂順序的書,在接下來m天中天天都會由於讀者的閱覽致使書籍順序改變位置。由於小豆被要求在接下來的m天中至少要整理一次圖書。小豆想知道,若是他前i天不去整理,第i天他的厭煩度是多少,這樣他好選擇厭煩度最小的那天去整理。
node

輸入輸出格式

輸入格式:ios

第一行會有兩個數,n,m分別表示有n本書,m天數組

接下來n行,每行兩個數,ai和vi,分別表示第i本書原本應該放在ai的位置,這本書有vi頁,保證不會有放置同一個位置的書spa

接下來m行,每行兩個數,xj和yj,表示在第j天的第xj本書會和第yj本書會由於讀者閱讀交換位置code

輸出格式:blog

一共m行,每行一個數,第i行表示前i天不去整理,第i天小豆的厭煩度,由於這個數可能很大,因此將結果模10^9 +7後輸出.ci

輸入輸出樣例

輸入樣例#1: 複製get

5 5
1 1
2 2
3 3
4 4
5 5
1 5
1 5
2 4
5 3
1 3string

輸出樣例#1: 複製hash

42
0
18
28
48

說明

對於20%的數據,1 ≤ ai; xj; yj ≤ n ≤ 5000, m ≤ 5000, vi ≤ 10^5

對於100%的數據,1 ≤ ai; xj; yj ≤ n ≤ 50000, m ≤ 50000, vi ≤ 10^5

Solution

看一波數據範圍,50000,5s。猜一波時間複雜度,\(nlogn^2\)?\(nlogn^3\)?\(nlogn^2\sqrt n\)?
想了一波樹套樹,發現能夠作。這裏我用的是樹狀數組套主席樹。
題目大意就是給你一些數對,每一個數有一個權值,也有一個厭煩度。
當一對數爲逆序對,而後算總厭煩度。能夠發現這題和[CQOI2011]動態逆序對很像,只不過這裏有一個厭煩度,動態逆序對那道題至關於權值爲1,因此這道題是那道題的升級版。
能夠理解,題目中所說的原本位置,就是指判斷當前這對數是不是逆序對中的標準,也就是逆序對中數的權值。
咱們每次只需統計前面比他小的數字厭煩度之和是多少,而且存下有多少個比他小,設當前數字的位置爲\(x\),它的原本位置爲\(a[x]\)(也就是判斷逆序對的權值),每一個數字的厭煩度爲\(w[i]\),因此當前這個數與其餘數產生的厭煩度爲
\[\sum_{i=1,a[x]<a[i]}^{x-1}w[i]+\sum_{i=x+1,a[x]>a[i]}^{n}w[i]\]
但想到若兩個交換的數字爲逆序對,那麼須要特殊判斷。
還要注意細節,本題要開\(long long\),並且要注意取模和空間問題。
主席樹的節點都開\(long long\)就會爆空間。
代碼以下:

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
struct TREE
{
    int ln,rn,shu;
    ll zhi;
}t[15001000];
int root[210000];
ll tot,a[101000],hash[101001],n,m,id[101000],w[109101];
ll qll[20101],qrr[20100],q1,q2,ge,ff=0;
ll lowbit(ll x) {return ((x)&(-x));}
void gai(int &node,int l,int r,ll hs,ll v,ll kk)
{
    if(!node) node=++tot;
    t[node].zhi+=v;
    t[node].shu+=kk;
    if(l==r) return;
    ll mid=(l+r)/2;
    if(hs<=mid) gai(t[node].ln,l,mid,hs,v,kk);
    else gai(t[node].rn,mid+1,r,hs,v,kk);
}
void add(ll p,ll v,ll kk){for(ll i=p;i<=n;i+=lowbit(i)) gai(root[i],1,n,hash[p],v,kk);}
ll SUM()
{
    ll ans1=0,ans2=0;ff=0;
    for(ll i=1;i<=q1;i++) ans1+=t[t[qrr[i]].ln].zhi,ff+=t[t[qrr[i]].ln].shu;
    for(ll i=1;i<=q2;i++) ans2+=t[t[qll[i]].ln].zhi,ff-=t[t[qll[i]].ln].shu;
    return ans1-ans2;
}
ll rk(ll qr,ll ql,ll l,ll r,ll k)
{
    q1=0;q2=0;ll ans=0;ge=0;
    for(ll i=qr;i>=1;i-=lowbit(i)) qrr[++q1]=root[i];
    for(ll i=ql;i>=1;i-=lowbit(i)) qll[++q2]=root[i];
    while(l<r)
    {
        ll mid=(l+r)/2;
        if(k<=a[mid])
        {
            for(ll i=1;i<=q1;i++) qrr[i]=t[qrr[i]].ln;
            for(ll i=1;i<=q2;i++) qll[i]=t[qll[i]].ln;
            r=mid;
        }
        else
        {
            ll lsiz=SUM();
            for(ll i=1;i<=q1;i++) qrr[i]=t[qrr[i]].rn;
            for(ll i=1;i<=q2;i++) qll[i]=t[qll[i]].rn;
            l=mid+1;ans+=lsiz;ge+=ff;
        }
    }
    return ans;
}
ll SUM1()
{
    ll ans1=0,ans2=0;ff=0;
    for(ll i=1;i<=q1;i++) ans1+=t[t[qrr[i]].rn].zhi,ff+=t[t[qrr[i]].rn].shu;
    for(ll i=1;i<=q2;i++) ans2+=t[t[qll[i]].rn].zhi,ff-=t[t[qll[i]].rn].shu;
    return ans1-ans2;
}
ll rkk(ll qr,ll ql,ll l,ll r,ll k)
{
    q1=0;q2=0;ll ans=0;ge=0;
    for(ll i=qr;i>=1;i-=lowbit(i)) qrr[++q1]=root[i];
    for(ll i=ql;i>=1;i-=lowbit(i)) qll[++q2]=root[i];
    while(l<r)
    {
        ll mid=(l+r)/2;
        if(k<=a[mid])
        {
            ll rsiz=SUM1();
            for(ll i=1;i<=q1;i++) qrr[i]=t[qrr[i]].ln;
            for(ll i=1;i<=q2;i++) qll[i]=t[qll[i]].ln;
            r=mid;ans+=rsiz;ge+=ff;
        }
        else
        {
            for(ll i=1;i<=q1;i++) qrr[i]=t[qrr[i]].rn;
            for(ll i=1;i<=q2;i++) qll[i]=t[qll[i]].rn;
            l=mid+1;
        }
    }
    return ans;
}
int main()
{
    ll x,y;
    long long ans=0;
    cin>>n>>m;
    for(ll i=1;i<=n;i++)
    scanf("%lld%lld",&a[i],&w[i]),hash[i]=a[i],id[a[i]]=i;
    sort(a+1,a+1+n);
    for(ll i=1;i<=n;i++)
    add(i,w[i],1);
    for(ll i=1;i<=n;i++)
    {
        ans+=rkk(i-1,0,1,n,hash[i]);
        ans+=rk(n,i,1,n,hash[i]);
    }
    for(ll i=1;i<=m;i++)
    {
        ll x1,y1;
        scanf("%lld%lld",&x,&y);
        x1=x;y1=y;
        ans-=(rkk(x1-1,0,1,n,hash[x1])+ge*w[x1]);
        ans-=(rk(n,x1,1,n,hash[x1])+ge*w[x1]);
        ans-=(rkk(y1-1,0,1,n,hash[y1])+ge*w[y1]);
        ans-=(rk(n,y1,1,n,hash[y1])+ge*w[y1]);
        if((x1<y1&&hash[x1]>hash[y1])||(x1>y1&&hash[x1]<hash[y1])) 
        ans+=w[x1]+w[y1];
        add(x1,-w[x1],-1);add(y1,-w[y1],-1);
        swap(hash[x1],hash[y1]);swap(w[x1],w[y1]);
        add(x1,w[x1],1);add(y1,w[y1],1);
        x1=x;y1=y;
        ans+=(rkk(x1-1,0,1,n,hash[x1])+ge*w[x1]);
        ans+=(rk(n,x1,1,n,hash[x1])+ge*w[x1]);
        ans+=(rkk(y1-1,0,1,n,hash[y1])+ge*w[y1]);
        ans+=(rk(n,y1,1,n,hash[y1])+ge*w[y1]);
        if((x1<y1&&hash[x1]>hash[y1])||(x1>y1&&hash[x1]<hash[y1]))
        ans-=(w[x1]+w[y1]);
        printf("%lld\n",ans%mod);
    }
}

博主蒟蒻,能夠隨意轉載,但必須附上原文連接k-z-j

相關文章
相關標籤/搜索