传送门

解题思路

  和以前做过的一道题有点像,就是区间逆序对之类的问题,用的是\(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]不勤劳的图书管理员(树套树)的更多相关文章

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

    Portal Description 给出一个\(1..n(n\leq5\times10^4)\)的排列\(\{a_n\}\)和数列\(\{w_n\}(w_i\leq10^5)\),进行\(m(m\l ...

  2. [P3759][TJOI2017]不勤劳的图书管理员(分块+树状数组)

    题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生 这两本书页数的和的厌烦度.现在有n本被打乱顺序的书 ...

  3. 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】

    题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...

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

    再也不作死写FhqTreap作内层树了,卡的不如暴力呜呜呜…… 题意翻译:给一个序列,每个下标包含两个属性$a$和$v$,求第一个属性与下标形成的所有逆序对的第二个属性和,给出$m$个交换两个下标的操 ...

  5. P3759 [TJOI2017]不勤劳的图书管理员 [树套树]

    树套树是什么啊我不知道/dk 我只知道卡常数w // by Isaunoya #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC o ...

  6. [TJOI2017]不勤劳的图书管理员(分块+树状数组)

    有一个数组开大会MLE开小会RE的做法:就是树套树,即树状数组套主席树,这种方法比较暴力,然而很遗憾它不能通过,因为其时空复杂度均为O(nlog2n). 想到一种不怎么耗内存,以时间换空间,分块!单次 ...

  7. 【bzoj4889】: [Tjoi2017]不勤劳的图书管理员 分块-BIT

    [bzoj4889]: [Tjoi2017]不勤劳的图书管理员 题目大意:给定一个序列(n<=50000),每个数有一个编码ai(ai<=50000)和权值vi(vi<=100000 ...

  8. 【BZOJ4889】[Tjoi2017]不勤劳的图书管理员 分块+树状数组

    [BZOJ4889][Tjoi2017]不勤劳的图书管理员 题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让 ...

  9. 【loj2639】[Tjoi2017]不勤劳的图书管理员

    #2639. 「TJOI2017」不勤劳的图书管理员 题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产 ...

随机推荐

  1. Socket错误详解及处理方法

    例如错误代码10061, 说明服务器已经找到,但连接被服务器拒绝, 连接失败原因可能是: 端口号设置错误: 2.服务器没有处于监听状态 (即ServerSocket –>Active=true) ...

  2. input只输入数字和小数后两位

    html:<input  name="" type="tel" value="" placeholder="请输入金额&qu ...

  3. Vagrant 手册之 box - 版本

    原文地址 从 Vagrant 1.5 版本起,box 开始支持版本.这运行创建 box 的人提交更新,使用 box 的人检查更新.更新 box 并查看变更记录. 对于 Vagrant 新手,box 版 ...

  4. JS创建表格完整

    <!DOCTYPE> <html> <head> <meta charset=utf-8 /> <title>动态表格</title& ...

  5. 边界安全 - CDN/DMZ/网络协议

    CDN   工具 - LuManager CDN DMZ 网络协议 - DNS Win7下搭建DNS服务器 - BIND 根域 顶级域(即相关国家域名管理机构的数据库,如中国的CNNIC) com n ...

  6. mysql的命令入门

    mysql入门实践 学习教程 教程链接地址 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据. 文 ...

  7. MyEclipse下Junit报错"The input type of the launch configuration"

    MyEclipse下Junit运行测试用例的时候报错: "The input type of the launch configuration does not exist" 原因 ...

  8. [原]Threads vs Processes in Linux 分析

    Linux中thread (light-weighted process) 跟process在實作上幾乎一樣. 最大的差異來自於,thread 會分享 virtual memory address s ...

  9. SQL server2000 创建表单的方法(已实践检验)

    我的系统是win7旗舰版的,在安装完SQL server2000之后,单击表,右键-新建表时,系统要么弹出:MMC检测到此管理单元发生一个错误.要么直接弹出microsoft sql server 2 ...

  10. adb shell常用命令总结

    一.文件操作相关命令 1.文件操作命令 子命令 参数 说明 cd 无 进入目录 cat [-beflnstuv] [-B bsize] [file...] 查看文件内容-n:显示行号-b:显示行号,但 ...