LUOGU P3759 [TJOI2017]不勤劳的图书管理员(树套树)
解题思路
和以前做过的一道题有点像,就是区间逆序对之类的问题,用的是\(BIT\)套权值线段树,交换时讨论一下计算答案。。跑的不如暴力快。。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=50005;
const int M=N*200;
const int MOD=1e9+7;
typedef long long LL;
inline int rd(){
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
}
int n,m,a[N],val[N],tot,rt[N];
LL ans;
struct Segment_Tree{
int sum[M],num[M],ls[M],rs[M];
void update_num(int &x,int l,int r,int pos,int k){
if(!x) x=++tot; num[x]+=k; num[x]%=MOD;
if(l==r) return; int mid=(l+r)>>1;
if(pos<=mid) update_num(ls[x],l,mid,pos,k);
else update_num(rs[x],mid+1,r,pos,k);
}
void update_sum(int &x,int l,int r,int pos,int k){
if(!x) x=++tot; (sum[x]+=k)%=MOD;
if(l==r) return; int mid=(l+r)>>1;
if(pos<=mid) update_sum(ls[x],l,mid,pos,k);
else update_sum(rs[x],mid+1,r,pos,k);
}
int query_sum(int x,int l,int r,int L,int R){
if(!x) return 0; if(L<=l && r<=R) return sum[x];
int mid=(l+r)>>1,ret=0;
if(L<=mid) ret+=query_sum(ls[x],l,mid,L,R);
if(mid<R) (ret+=query_sum(rs[x],mid+1,r,L,R))%=MOD;
return ret;
}
int query_num(int x,int l,int r,int L,int R){
if(!x) return 0; if(L<=l && r<=R) return num[x];
int mid=(l+r)>>1,ret=0;
if(L<=mid) ret+=query_num(ls[x],l,mid,L,R);
if(mid<R) (ret+=query_num(rs[x],mid+1,r,L,R))%=MOD;
return ret;
}
}tree2;
struct BIT{
inline void add(int x,int k){
for(int i=x;i<=n;i+=i&-i) {
tree2.update_num(rt[i],1,50000,a[x],k);
tree2.update_sum(rt[i],1,50000,a[x],k*val[x]);
}
}
inline int query_sum(int l,int r,int L,int R){
if(l>r || L>R) return 0; int ret=0;
for(int i=r;i;i-=i&-i) (ret+=tree2.query_sum(rt[i],1,50000,L,R))%=MOD;
for(int i=l-1;i;i-=i&-i) (ret-=tree2.query_sum(rt[i],1,50000,L,R))%=MOD;
return (ret+MOD)%MOD;
}
inline int query_num(int l,int r,int L,int R){
if(l>r || L>R) return 0; int ret=0;
for(int i=r;i;i-=i&-i) (ret+=tree2.query_num(rt[i],1,50000,L,R))%=MOD;
for(int i=l-1;i;i-=i&-i) (ret-=tree2.query_num(rt[i],1,50000,L,R))%=MOD;
return (ret+MOD)%MOD;
}
}tree1;
int main(){
n=rd(),m=rd(); int x,y,tmp,num,num1,num2;
for(int i=1;i<=n;i++){
a[i]=rd(),val[i]=rd(); tree1.add(i,1);
ans+=tree1.query_sum(1,i,a[i]+1,50000);
ans+=1ll*tree1.query_num(1,i,a[i]+1,50000)*val[i]%MOD;
ans%=MOD;
} LL sum;
while(m--){
x=rd(),y=rd(); if(x>y) swap(x,y);
if(x==y) {printf("%lld\n",ans); continue;}
if(a[x]<a[y]) (ans+=val[x]+val[y])%=MOD;
else (ans-=val[x]+val[y])%=MOD;
tmp=tree1.query_sum(x+1,y-1,min(a[x],a[y]),max(a[x],a[y]));
num=tree1.query_num(x+1,y-1,min(a[x],a[y]),max(a[x],a[y]));
num1=tree1.query_num(x+1,y-1,1,min(a[x],a[y])-1);
num2=tree1.query_num(x+1,y-1,max(a[x],a[y])+1,50000);
if(a[x]<a[y]) ans+=tmp*2%MOD+1ll*num*(val[x]+val[y])%MOD,ans%=MOD;
else ans-=tmp*2%MOD+1ll*num*(val[x]+val[y])%MOD,ans%=MOD;
sum=1ll*(val[y]-val[x])*num1%MOD+1ll*(val[x]-val[y])*num2%MOD; sum%=MOD;
(ans+=sum)%=MOD;
tree1.add(x,-1); tree1.add(y,-1); swap(a[x],a[y]); swap(val[x],val[y]);
tree1.add(x,1); tree1.add(y,1); ans=(ans+MOD)%MOD; printf("%lld\n",ans);
}
return 0;
}
LUOGU P3759 [TJOI2017]不勤劳的图书管理员(树套树)的更多相关文章
- 洛谷P3759 - [TJOI2017]不勤劳的图书管理员
Portal Description 给出一个\(1..n(n\leq5\times10^4)\)的排列\(\{a_n\}\)和数列\(\{w_n\}(w_i\leq10^5)\),进行\(m(m\l ...
- [P3759][TJOI2017]不勤劳的图书管理员(分块+树状数组)
题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生 这两本书页数的和的厌烦度.现在有n本被打乱顺序的书 ...
- 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】
题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...
- Luogu 3759 [TJOI2017]不勤劳的图书管理员
再也不作死写FhqTreap作内层树了,卡的不如暴力呜呜呜…… 题意翻译:给一个序列,每个下标包含两个属性$a$和$v$,求第一个属性与下标形成的所有逆序对的第二个属性和,给出$m$个交换两个下标的操 ...
- P3759 [TJOI2017]不勤劳的图书管理员 [树套树]
树套树是什么啊我不知道/dk 我只知道卡常数w // by Isaunoya #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC o ...
- [TJOI2017]不勤劳的图书管理员(分块+树状数组)
有一个数组开大会MLE开小会RE的做法:就是树套树,即树状数组套主席树,这种方法比较暴力,然而很遗憾它不能通过,因为其时空复杂度均为O(nlog2n). 想到一种不怎么耗内存,以时间换空间,分块!单次 ...
- 【bzoj4889】: [Tjoi2017]不勤劳的图书管理员 分块-BIT
[bzoj4889]: [Tjoi2017]不勤劳的图书管理员 题目大意:给定一个序列(n<=50000),每个数有一个编码ai(ai<=50000)和权值vi(vi<=100000 ...
- 【BZOJ4889】[Tjoi2017]不勤劳的图书管理员 分块+树状数组
[BZOJ4889][Tjoi2017]不勤劳的图书管理员 题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让 ...
- 【loj2639】[Tjoi2017]不勤劳的图书管理员
#2639. 「TJOI2017」不勤劳的图书管理员 题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产 ...
随机推荐
- day23—JavaScript实现DIV盒子拖拽(原生方式)
转行学开发,代码100天——2018-04-08 <!doctype html> <html> <head> <meta charset="utf- ...
- pandas melt 与pivot 函数
(掌握这个,基本就完美无缺的任意按照自己的想法,更改列了.) 背景: 最近有个excel 数据需要转化的过程. 数据量还挺大的,大概有30多万. 需要把某些行变成列,有些列又变成行. 这个操作本身就比 ...
- 解决BootstrapTable设置height属性后,表格不对齐的问题
解决BootstrapTable设置height属性后,表格不对齐的问题 2018年03月06日 09:56:54 nb7474 阅读数 5920 一般在使用BootstrapTable 插件 ...
- JS原型链详解
最近面试被问到了就决定好好深入理解原型链 对象 要清楚原型链,首先要弄清楚对象: 普通对象 最普通的对象:有__proto__属性(指向其原型链),没有prototype属性. 原型对象(person ...
- Oh My God!e.printStackTrace() 导致系统卡崩
作者:sxgkwei 来源:http://dwz.cn/tQe4fLeDe.printStackTrace() 会导致锁死?这仅仅是打印啊,怎么可能?!先别惊呼不可能,且听我细细道来.先看截图1:注意 ...
- JQuery的链式编程与隐式迭代
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- tornado后台小框架
import tornado.ioloop import tornado.web """使用get方法提交过来数据就是用get方法,使用post执行post方法这个框架的 ...
- C#设计模式:装饰者模式(Decorator Pattern)
一,装饰者模式(Decorator Pattern):装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能. 二,在以上代码中我们是中国人是根本行为,我们给中国人装饰我会说英语 ...
- 自己实现一个类似 jQuery 的函数库
假如我们有一个需求,需要给元素添加样式类,使用原生的JS很容易搞定. 1 抽取函数 function addClass(node, className){ node.classList.add(cla ...
- elasticsearch 基础 —— Field Collapsing字段折叠
允许根据字段值折叠搜索结果.通过按折叠键选择顶部排序文档来完成折叠.例如,下面的查询检索每个用户的最佳推文,并按喜欢的数量对它们进行排序. GET /twitter/_search { "q ...