列表

详情


NC20596. [TJOI2017]不勤劳的图书管理员

描述

加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员。他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度。现在有n本被打乱顺序的书,在接下来m天中每天都会因为读者的阅览导致书籍顺序改变位置。因为小豆被要求在接下来的m天中至少要整理一次图书。小豆想知道,如果他前i天不去整理,第i天他的厌烦度是多少,这样他好选择厌烦度最小的那天去整理。

输入描述

第一行会有两个数,n,m分别表示有n本书,m天
接下来n行,每行两个数,ai和vi,分别表示第i本书本来应该放在ai的位置,这本书有vi页,保证不会有放置同一个位置的书
接下来m行,每行两个数,xj和yj,表示在第j天的第xj本书会和第yj本书会因为读者阅读交换位置

输出描述

一共m行,每行一个数,第i行表示前i天不去整理,第i天小豆的厌烦度,因为这个数可能很大,所以将结果模10^9 +7后输出

示例1

输入:

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

输出:

42
0
18
28
48

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 1641ms, 内存消耗: 45416K, 提交时间: 2019-03-09 18:28:11

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=50010;
const ll mod=1000000007;
ll ans;
int n,m,B;
ll s[2][250][maxn],v[maxn];
int p[maxn];
int rd()
{
    int ret=0;  char gc=getchar();
    while(gc<'0'||gc>'9') gc=getchar();
    while(gc>='0'&&gc<='9')   ret=ret*10+gc-'0',gc=getchar();
    return ret;
}
void updata(int z,int y,int x,ll val)
{
    if(!x)  return ;
    for(int i=x;i<=n;i+=i&-i)    s[z][y][i]=(s[z][y][i]+val+mod)%mod;
}
ll query(int z,int y,int x)
{
    if(x<0)  return 0;
    ll ret=0;
    for(int i=x;i;i-=i&-i)  ret=(ret+s[z][y][i])%mod;
    return ret;
}
void calc(int a,int b,int c)
{
    if(p[a]<p[c])    ans=(ans+v[a]+v[c])%mod;
    else    ans=(ans-v[a]-v[c]+mod+mod)%mod;
    if(p[b]<p[c])    ans=(ans-v[b]-v[c]+mod+mod)%mod;
    else    ans=(ans+v[b]+v[c])%mod;
}
int main()
{
    int i,j,a,b,c,d;
    n=rd(),m=rd(),B=int(sqrt(n*17));
    for(i=0;i<n;i++) p[i]=rd(),v[i]=rd(),updata(0,i/B,p[i],v[i]),updata(1,i/B,p[i],1);
    for(i=n-1;i>=0;i--)
    {
        ans=(ans+query(0,n/B+1,p[i])+query(1,n/B+1,p[i])*v[i])%mod;
        updata(0,n/B+1,p[i],v[i]),updata(1,n/B+1,p[i],1);
    }
    for(i=1;i<=m;i++)
    {
        a=rd()-1,b=rd()-1;
        if(a==b)
        {
            printf("%lld\n",ans);
            continue;
        }
        if(a>b)  swap(a,b);
        c=a/B,d=b/B;
        if(p[a]<p[b])    ans=(ans+v[a]+v[b])%mod;
        else    ans=(ans-v[a]-v[b]+mod+mod)%mod;
        if(c==d)
        {
            for(j=a+1;j<b;j++)   calc(a,b,j);
            swap(p[a],p[b]),swap(v[a],v[b]);
            printf("%lld\n",ans);
            continue;
        }
        for(j=a+1;j<c*B+B;j++)   calc(a,b,j);
        for(j=d*B;j<b;j++)   calc(a,b,j);
        for(j=c+1;j<d;j++)
        {
            ans=(ans-2*query(0,j,p[a])+query(0,j,n)-(2*query(1,j,p[a])-B+mod)*v[a]%mod+mod)%mod;
            ans=(ans+2*query(0,j,p[b])-query(0,j,n)+(2*query(1,j,p[b])-B+mod)*v[b]%mod+mod)%mod;
        }
        updata(0,c,p[a],-v[a]),updata(0,d,p[b],-v[b]),updata(1,c,p[a],-1),updata(1,d,p[b],-1);
        swap(p[a],p[b]),swap(v[a],v[b]);
        updata(0,c,p[a],v[a]),updata(0,d,p[b],v[b]),updata(1,c,p[a],1),updata(1,d,p[b],1);
        printf("%lld\n",ans);
    }
    return 0;
}

上一题