Luogu 3759 [TJOI2017]不勤劳的图书管理员

2023-11-06 09:59

本文主要是介绍Luogu 3759 [TJOI2017]不勤劳的图书管理员,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

再也不作死写FhqTreap作内层树了,卡的不如暴力呜呜呜…… 

题意翻译:给一个序列,每个下标包含两个属性$a$和$v$,求第一个属性与下标形成的所有逆序对的第二个属性和,给出$m$个交换两个下标的操作,每次操作之后查询。

考虑一下交换之后会发生什么:

假设这次要交换$x$和$y$,使$x \leq y$。

发现交换之后$x, y$和$x$的左边的数和$y$右边的数构成的逆序对产生的贡献不变,发生变化的是中间的数。

那么问题就简单了,只要先消去中间的数和$x, y$的贡献,具体来说就是$[x + 1, y - 1]$这个区间中$a_{i}$比$a_{x}$小的$b_{i}$和,以及$a_{i}$比$a_{y}$大的$b_{i}$和。

发现$(x, y)$可能也会构成一个逆序对,拎出来判一下可以保证这一对只被计算一次。

然后算一下交换之后产生的贡献,方法类似。

树套树维护即可。

时间复杂度$O(nlog^{2}n)$。

Code:

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;const int N = 5e4 + 5;
const int M = 2e7 + 5;
const ll P = 1e9 + 7;int n, m, a[N];
ll v[N], ans = 0LL;template <typename T>
inline void read(T &X) {X = 0; char ch = 0; T op = 1;for(; ch > '9' || ch < '0'; ch = getchar())if(ch == '-') op = -1;for(; ch >= '0' && ch <= '9'; ch = getchar())X = (X << 3) + (X << 1) + ch - 48;X *= op;
}template <typename T>
inline void swap(T &x, T &y) {T t = x; x = y; y = t;
}namespace BinaryIndexTree {int cnt[N]; ll s[N];#define lowbit(x) (x & (-x))inline void modifyS(int p, ll val) {for(; p <= n; p += lowbit(p)) s[p] = (s[p] + val) % P;}inline void modifyC(int p) {for(; p <= n; p += lowbit(p)) cnt[p]++;}inline ll getSum(int p) {ll res = 0;for(; p > 0; p -= lowbit(p)) res = (res + s[p]) % P;return res;}inline int getCnt(int p) {int res = 0;for(; p > 0; p -= lowbit(p)) res += cnt[p];return res;}#undef lowbit} using namespace BinaryIndexTree;namespace Tree {int nodeCnt, root[N * 30];struct Node {int lc, rc, siz;ll sum;} s[M];#define mid ((l + r) >> 1)inline void up(int p) {if(!p) return;s[p].siz = s[s[p].lc].siz + s[s[p].rc].siz;s[p].sum = (s[s[p].lc].sum + s[s[p].rc].sum) % P;}void modify(int &p, int l, int r, int x, ll selV) {if(!p) p = ++nodeCnt;if(l == r) {s[p].siz = (selV != -1);s[p].sum = (selV == -1 ? 0 : selV % P);return;}if(x <= mid) modify(s[p].lc, l, mid, x, selV);else modify(s[p].rc, mid + 1, r, x, selV);up(p);}ll query(int p, int l, int r, int x, int y, ll selV) {if(!p) return 0LL;if(x <= l && y >= r) return (selV * s[p].siz % P + s[p].sum) % P;ll res = 0LL;if(x <= mid) res = (res + query(s[p].lc, l, mid, x, y, selV)) % P;if(y > mid) res = (res + query(s[p].rc, mid + 1, r, x, y, selV)) % P;return res;}#define lowbit(p) (p & (-p))inline void change(int p, int val, ll selV) {for(; p <= n; p += lowbit(p))modify(root[p], 1, n, val, selV);}inline void clear(int p, int val) {for(; p <= n; p += lowbit(p))modify(root[p], 1, n, val, -1);}inline ll ask(int p, int v, ll selV, int type) {ll res = 0LL;for(; p > 0; p -= lowbit(p)) {if(type) res = (res + query(root[p], 1, n, v + 1, n, selV)) % P;else res = (res + query(root[p], 1, n, 1, v - 1, selV)) % P;}return res;}inline ll qSum(int l, int r, int v, ll selV, int type) {return (ask(r, v, selV, type) - ask(l - 1, v, selV, type) + P) % P;}} using namespace Tree;int main() {read(n), read(m);nodeCnt = 0;for(int i = 1; i <= n; i++) {read(a[i]), read(v[i]);ans = (ans + (getSum(n) - getSum(a[i]) + P) % P + P + v[i] * (getCnt(n) - getCnt(a[i])) % P + P) % P;modifyS(a[i], v[i]), modifyC(a[i]);change(i, a[i], v[i]);}for(int x, y; m--; ) {read(x), read(y);if(x == y) {printf("%lld\n", ans);continue;}if(x > y) swap(x, y);ll res = 0LL;if(x + 1 <= y - 1) {res = (res + qSum(x + 1, y - 1, a[y], v[y], 1)) % P;res = (res + qSum(x + 1, y - 1, a[x], v[x], 0)) % P;}if(a[y] < a[x]) res = ((res + v[x]) % P + v[y]) % P;ans = (ans - res + P) % P;res = 0LL;if(x + 1 <= y - 1) {res = (res + qSum(x + 1, y - 1, a[y], v[y], 0)) % P;res = (res + qSum(x + 1, y - 1, a[x], v[x], 1)) % P;}if(a[y] > a[x]) res = ((res + v[x]) % P + v[y]) % P;ans = (ans + res) % P;printf("%lld\n", ans);clear(x, a[x]), clear(y, a[y]);change(x, a[y], v[y]), change(y, a[x], v[x]);swap(a[x], a[y]), swap(v[x], v[y]);}return 0;
}
树状数组套线段树(100 pts)
// luogu-judger-enable-o2
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
typedef long long ll;const int N = 5e4 + 5;
const int M = 2e7 + 5;
const ll P = 1e9 + 7;int n, m, a[N];
ll v[N], ans = 0;namespace FhqTreap {int root[M], nodeCnt, ch[M][2], pri[M], siz[M];ll key[M], sum[M], sel[M];#define lc ch[p][0]#define rc ch[p][1]inline void up(int p) {if(p) {siz[p] = siz[lc] + siz[rc] + 1;sum[p] = (sum[lc] % P + sum[rc] % P + sel[p] % P) % P;}}inline int newnode(ll val, ll selV) {++nodeCnt;key[nodeCnt] = val, sum[nodeCnt] = sel[nodeCnt] = selV;pri[nodeCnt] = rand(), siz[nodeCnt] = 1;return nodeCnt;}void split(int p, ll val, int &x, int &y) {if(!p) x = y = 0;else {if(val >= key[p])x = p, split(rc, val, rc, y);else y = p, split(lc, val, x, lc);up(p);}}int merge(int x, int y) {if(!x || !y) return x + y;else {if(pri[x] < pri[y]) {ch[x][1] = merge(ch[x][1], y);up(x);return x;} else {ch[y][0] = merge(x, ch[y][0]);up(y);return y;}    }    }inline void insert(int rt, ll val, ll selV) {if(!root[rt]) {root[rt] = newnode(val, selV);return;}int x, y;split(root[rt], val, x, y);root[rt] = merge(x, merge(newnode(val, selV), y));}inline void remove(int rt, ll val) {int x, y, z;split(root[rt], val, x, y);split(x, val - 1, x, z);z = merge(ch[z][0], ch[z][1]);root[rt] = merge(merge(x, z), y);}inline ll ask(int rt, ll val, ll selV, int type) {int x, y; ll res;if(type) {split(root[rt], val, x, y);res = (selV * siz[x] % P + sum[x]) % P; } else {split(root[rt], val, x, y);res = (selV * siz[y] % P + sum[y]) % P;}root[rt] = merge(x, y);return res % P;}void Pi(int p, int *arr) {if(lc) Pi(lc, arr);printf("%d ", arr[p]);if(rc) Pi(rc, arr);}#undef lc#undef rc
};namespace SegT {using namespace FhqTreap;#define lc p << 1#define rc p << 1 | 1#define mid ((l + r) >> 1)void ins(int p, int l, int r, int x, ll val, ll selV) {insert(p, val, selV);if(l == r) return;if(x <= mid) ins(lc, l, mid, x, val, selV);else ins(rc, mid + 1, r, x, val, selV);}void del(int p, int l, int r, int x, ll val) {remove(p, val);if(l == r) return;if(x <= mid) del(lc, l, mid, x, val);else del(rc, mid + 1, r, x, val);}ll query(int p, int l, int r, int x, int y, ll val, ll selV, int type) {if(x <= l && y >= r) return ask(p, val, selV, type) % P;ll res = 0;if(x <= mid) res = (res + query(lc, l, mid, x, y, val, selV, type)) % P;if(y > mid) res = (res + query(rc, mid + 1, r, x, y, val, selV, type)) % P;return res;}void print(int p, int l, int r, int *arr) {Pi(root[p], arr), printf("\n");if(l == r) return;print(lc, l, mid, arr), print(rc, mid + 1, r, arr);}} using namespace SegT;template <typename T>
inline void swap(T &x, T &y) {T t = x;x = y;y = t;
}namespace IOstream{const int L = 1 << 15;char buffer[L], *S, *T;inline char Getchar() {if(S == T) {T = (S = buffer) + fread(buffer, 1, L, stdin);if(S == T) return EOF;}return *S++;}template <class T> inline void read(T &X) {char ch; T op = 1;for(ch = Getchar(); ch > '9' || ch < '0'; ch = Getchar())if(ch == '-') op = -1;for(X = 0; ch >= '0' && ch <= '9'; ch = Getchar()) X = (X << 1) + (X << 3) + ch - '0'; X *= op;}template <typename T>inline void write(T x){T sta[15]; int len = 0;if(x < 0) putchar('-'), x = -x;if(x == 0) {putchar('0');return;}for(; x > 0; sta[++len] = x % 10, x /= 10);for(int i = len; i >= 1; i--) putchar(sta[i] + '0');}} using namespace IOstream;namespace BinaryIndexTree {int cnt[N]; ll s[N];#define lowbit(x) (x & (-x))inline void modifyS(int p, ll val) {for(; p <= n; p += lowbit(p)) s[p] = (s[p] + val) % P;}inline void modifyC(int p) {for(; p <= n; p += lowbit(p)) cnt[p]++;}inline ll getSum(int p) {ll res = 0;for(; p > 0; p -= lowbit(p)) res = (res + s[p]) % P;return res;}inline int getCnt(int p) {int res = 0;for(; p > 0; p -= lowbit(p)) res += cnt[p];return res;}} using namespace BinaryIndexTree;int main() {
//    freopen("1.in", "r", stdin);
//    freopen("mine.out", "w", stdout);//    srand(19260817);
    read(n), read(m);nodeCnt = 0;for(int i = 1; i <= n; i++) {read(a[i]), read(v[i]);ans = (ans + (getSum(n) - getSum(a[i]) + P) % P + P + v[i] * (getCnt(n) - getCnt(a[i])) % P + P) % P;modifyS(a[i], v[i]), modifyC(a[i]);ins(1, 1, n, i, a[i], v[i]);}//    printf("%d\n", ans);for(int x, y; m--; ) {read(x), read(y);if(x == y) {printf("%lld\n", ans);continue;}if(x > y) swap(x, y);ll res = 0;if(x + 1 <= y - 1) {res = (res + query(1, 1, n, x + 1, y - 1, a[y], v[y], 0)) % P;res = (res + query(1, 1, n, x + 1, y - 1, a[x], v[x], 1)) % P; }if(a[y] < a[x]) res = (res % P + v[x] % P + v[y] % P) % P;ans = (ans - res + P) % P;res = 0;if(x + 1 <= y - 1) {res = (res + query(1, 1, n, x + 1, y - 1, a[y], v[y], 1)) % P;res = (res + query(1, 1, n, x + 1, y - 1, a[x], v[x], 0)) % P; }if(a[y] > a[x]) res = (v[y] % P + v[x] % P + res % P) % P;ans = (ans + res) % P;write(ans), puts("");del(1, 1, n, x, a[x]), del(1, 1, n, y, a[y]);ins(1, 1, n, y, a[x], v[x]), ins(1, 1, n, x, a[y], v[y]);swap(a[x], a[y]), swap(v[x], v[y]);/*        print(1, 1, n, key), printf("\n");print(1, 1, n, sel), printf("\n");   */}return 0;
}
线段树套fhqTreap (20 pts)

 

转载于:https://www.cnblogs.com/CzxingcHen/p/9577938.html

这篇关于Luogu 3759 [TJOI2017]不勤劳的图书管理员的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/355925

相关文章

图书管理系统系统分享

分享一个图书管理系统,Java、SpringBoot、Vue和MySQL开发的图书馆管理系统 gitee项目地址:https://gitee.com/yuanmomoya/open-source-project/tree/master/books-management-system GitHub项目地址:https://github.com/yuanmomoya/open-source-pro

基于springboot+vue+uniapp的“共享书角”图书借还管理系统小程序

开发语言:Java框架:springboot+uniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9 系统展示 后台登录界面 管理员功能界面 出借者管理 图书信息管理 图书归还管理 出租收入管理

FHQ Treap模版(luogu P3369)

FHQ Treap模版(自用),带注释 #include<bits/stdc++.h>using namespace std;const int N=1e5+10;int n,root,idx;struct node{int l,r;int val,key,size;}tr[N];int getnew(int v){tr[++idx].val=v;//权值tr[idx].key=rand(

当当图书福利券,满400减230,别说我没告诉你!

1024程序员节 当当网计算机图书 每满100减50! 满200减100! 满300-150! 机械工业出版社华章公司联合当当网特意为【大数据技术与架构】用户申请了一批可与满减叠加使用的“满200减30”的图书优惠码,优惠码使用后相当于: 400减230 !!!   优惠码:【YRMQMY】(注意区分大小写) 使用渠道:当当app和当当小程序 使用时间:10月22-10月31 本活动满减与礼券

智能图书推荐系统:Spring Boot技术深度解析

4 系统设计 4.1系统概要设计 本图书个性化推荐系统选择B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式。适合在互联网上进行操作,只要学生能连网,任何时间、任何地点都可以进行系统的操作使用。系统工作原理图如图4-1所示: 图4-1 系统工作原理图 4.2系统结构设计 整个系统是由多个功能模块组合而成的,要将所有的功能模块都一一列举出来,然后进行逐个的功能

个性化阅读体验:Spring Boot框架的图书推荐解决方案

第5章 系统详细设计 5.1前台首页功能模块 图书个性化推荐系统,在前台首页可以查看首页、图书信息、好书推荐、留言反馈、个人中心、后台管理等内容,如图5-1所示。 图5-1首页功能界面图 学生注册、登录,在学生注册页面可以填写学号、密码、学生姓名、性别、出生日期、联系电话、班级等信息进行注册、登录,如图5-2所示。 图5-2学生注册、登录界面图 图书信息,在图书信息页面通过查看图书

数据库课程设计mysql---图书管理系统详细的设计文档和需求文档

图书管理系统设计文档与需求文档 一、项目概述 项目名称:图书管理系统 项目背景:随着图书馆规模的扩大和图书数量的增加,传统的手工管理方式已难以满足现代图书馆高效、精准的管理需求。因此,开发一套基于MySQL的图书管理系统,旨在通过信息化手段实现图书的录入、借阅、归还、查询及用户管理等功能的自动化,提高图书馆的工作效率和服务质量。 项目目标: 实现图书信息的电子化存储与管理。提供便捷的图书

爬虫一:获取豆瓣图书Top250(Requests+XPath)

目的: 获取豆瓣图书Top250的所有书目信息。 豆瓣网址:https://book.douban.com/top250 代码: import requestsfrom lxml import etreeimport timefor i in range(10):url = 'https://book.douban.com/top250?start=' + str(25*i)data

Django+Vue协同过滤算法图书推荐系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 需要的环境3.2 Django接口层3.3 实体类3.4 config.ini3.5 启动类3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质创作者,全网30w+粉丝,超300w访问量,专注于大学生项目实战开发、讲

重生之当IT管理员遇到数据摆渡界“悟空”

您可以搜索“飞驰云联”了解更多信息。 关于飞驰云联 飞驰云联是中国领先的数据安全传输解决方案提供商,长期专注于安全可控、性能卓越的数据传输技术和解决方案,公司产品和方案覆盖了跨网跨区域的数据安全交换、供应链数据安全传输、数据传输过程的防泄漏、FTP的增强和国产化替代、文件传输自动化和传输集成等各种数据传输场景。飞驰云联主要服务于集成电路半导体、先进制造、高科技、金融、政府机构等行业的中大型