Loading [MathJax]/jax/output/CommonHTML/fonts/TeX/AMS-Regular.js

BZOJ4889: [TJOI2017]不勤劳的图书管理员

BZOJ4889: [TJOI2017]不勤劳的图书管理员

额,这个题由于被卡评测了,于是变成了权限题。。。

本蒟蒻表示没钱氪金。。。

当然,可以去洛谷/LOJLOJ搞搞事。。。

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

LOJ#2639. 「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
输出样例#1: 复制
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


题解Here!

首先,题目可以转化为:

  1. 区间询问关键字<x<x的元素个数,和这些元素的valval之和。
  2. 单点修改。

对某一本书统计厌烦度时只需这么统计:ans+=给它作出贡献的书的总页数+给它作出贡献的书的个数×自己的页数

然后这个显然树套树维护。

我用了树状数组套动态开点权值线段树。

网上还有分块套树状数组的题解,太神了。。。

本蒟蒻好菜啊。。。

附代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 50010
#define MOD 1000000007LL
using namespace std;
int n,m;
long long ans=0;
int root[MAXN];
struct Book{
    int x,val;
}book[MAXN];
inline int read(){
    int date=0,w=1;char c=0;
    while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    return date*w;
}
inline int lowbit(int x){return x&(-x);}
namespace BIT{
    long long s[MAXN],sum[MAXN];
    inline void add(int x,long long v){for(;x<=n;x+=lowbit(x)){s[x]++;sum[x]+=v;}}
    inline long long get_num(int x){long long ans=0;for(;x;x-=lowbit(x))ans+=s[x];return ans;}
    inline long long get_sum(int x){long long ans=0;for(;x;x-=lowbit(x))ans+=sum[x];return ans;}
}
namespace ST{
    #define LSON(rt) a[rt].lson
    #define RSON(rt) a[rt].rson
    #define SUM(rt) a[rt].sum
    #define DATA(rt) a[rt].data
    int size=0;
    struct Segment_Tree{
        long long sum;
        int data,lson,rson;
    }a[MAXN<<8];
    void update(int k,int v,int c,int lside,int rside,int &rt){
        if(!rt)rt=++size;
        DATA(rt)+=c;SUM(rt)+=v;
        if(lside==rside)return;
        int mid=lside+rside>>1;
        if(k<=mid)update(k,v,c,lside,mid,LSON(rt));
        else update(k,v,c,mid+1,rside,RSON(rt));
    }
    long long query_num(int l,int r,int lside,int rside,int rt){
        if(!rt)return 0;
        long long ans=0;
        if(l<=lside&&rside<=r)return DATA(rt);
        int mid=lside+rside>>1;
        if(l<=mid)ans+=query_num(l,r,lside,mid,LSON(rt));
        if(mid<r)ans+=query_num(l,r,mid+1,rside,RSON(rt));
        return ans;
    }
    long long query_sum(int l,int r,int lside,int rside,int rt){
        if(!rt)return 0;
        long long ans=0;
        if(l<=lside&&rside<=r)return SUM(rt);
        int mid=lside+rside>>1;
        if(l<=mid)ans+=query_sum(l,r,lside,mid,LSON(rt));
        if(mid<r)ans+=query_sum(l,r,mid+1,rside,RSON(rt));
        return ans;
    }
}
inline void update(int x,int k,int v,int c){for(;x<=n;x+=lowbit(x))ST::update(k,v,c,1,n,root[x]);}
inline long long query_num(int x,int y,int l,int r){
    if(x>y||l>r)return 0;
    long long ans=0;
    for(;y;y-=lowbit(y))ans+=ST::query_num(l,r,1,n,root[y]);
    for(--x;x;x-=lowbit(x))ans-=ST::query_num(l,r,1,n,root[x]);
    return ans;
}
inline long long query_sum(int x,int y,int l,int r){
    if(x>y||l>r)return 0;
    long long ans=0;
    for(;y;y-=lowbit(y))ans+=ST::query_sum(l,r,1,n,root[y]);
    for(--x;x;x-=lowbit(x))ans-=ST::query_sum(l,r,1,n,root[x]);
    return ans;
}
void work(){
    int x,y;
    while(m--){
        x=read();y=read();
        if(x==y){
            printf("%lld\n",ans);
            continue;
        }
        if(x>y)swap(x,y);
         
        //--------------------------------------------------------------------------------
         
        ans=(ans+query_sum(x+1,y-1,1,book[y].x-1)%MOD+query_num(x+1,y-1,1,book[y].x-1)*book[y].val%MOD)%MOD;
        ans=((ans-query_sum(x+1,y-1,book[y].x+1,n)%MOD+MOD)%MOD-query_num(x+1,y-1,book[y].x+1,n)*book[y].val%MOD+MOD)%MOD;
         
        //--------------------------------------------------------------------------------
         
        ans=(ans+query_sum(x+1,y-1,book[x].x+1,n)%MOD+query_num(x+1,y-1,book[x].x+1,n)*book[x].val%MOD)%MOD;
        ans=((ans-query_sum(x+1,y-1,1,book[x].x-1)%MOD+MOD)%MOD-query_num(x+1,y-1,1,book[x].x-1)*book[x].val%MOD+MOD)%MOD;
         
        //--------------------------------------------------------------------------------
         
        if(book[x].x>book[y].x)ans=(ans-book[x].val-book[y].val+MOD)%MOD;
        else ans=(ans+book[x].val+book[y].val)%MOD;
         
        //--------------------------------------------------------------------------------
         
        update(x,book[x].x,-book[x].val,-1);update(y,book[y].x,-book[y].val,-1);
        swap(book[x].x,book[y].x);swap(book[x].val,book[y].val);
        update(x,book[x].x,book[x].val,1);update(y,book[y].x,book[y].val,1);
         
        //--------------------------------------------------------------------------------
         
        printf("%lld\n",ans);
    }
}
void init(){
    n=read();m=read();
    for(int i=1;i<=n;i++){
        book[i].x=read();book[i].val=read();
        update(i,book[i].x,book[i].val,1);
    }
    for(int i=n;i>=1;i--){
        BIT::add(book[i].x,book[i].val);
        ans=(ans+BIT::get_sum(book[i].x-1)%MOD+BIT::get_num(book[i].x-1)*book[i].val%MOD)%MOD;
    }
}
int main(){
    init();
    work();
    return 0;
}

 

posted @   符拉迪沃斯托克  阅读(317)  评论(0编辑  收藏  举报
编辑推荐:
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
阅读排行:
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· 软件产品开发中常见的10个问题及处理方法
· Vite CVE-2025-30208 安全漏洞
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· MQ 如何保证数据一致性?
Live2D
欢迎阅读『BZOJ4889: [TJOI2017]不勤劳的图书管理员』
点击右上角即可分享
微信分享提示