【bzoj4889】: [Tjoi2017]不勤劳的图书管理员 分块-BIT
【bzoj4889】: [Tjoi2017]不勤劳的图书管理员
题目大意:给定一个序列(n<=50000),每个数有一个编码ai(ai<=50000)和权值vi(vi<=100000),每次交换两个数的位置,交换m次(m<=50000)
求每次交换后的序列的杂乱度对1e9+7取模(对于每一对是逆序对的编码会产生两者权值和的杂乱度)。
感觉正解是什么奇怪的树套树?蒟蒻只会分块水题。。
先用BIT求一遍初始状态的杂乱度。。(不要问我为什么一开始是BIT。。因为打暴力正好用到就懒得改了。。感觉直接分块也行)
然后开始分块。。分块完对每个块内排序,然后求出排序完之后的权值前缀和。
考虑每次交换操作,若原有序列是 A B C D E,交换B D
那么其实改变的杂乱度只跟B->D的序列有关,跟A E无关
仔细讨论一下就是
当aB<aD
改变的杂乱度会是
C段里所有编号比aB大的权值和 + C段里所有编号比aB大的个数*vB - C段里所有编号比aB小的权值和 - C段里所有编号比aB小的个数*vB
C段里所有编号比aD小的权值和 + C段里所有编号比aD小的个数*vD - C段里所有编号比aD大的权值和 - C段里所有编号比aD大的个数*vD
当aB>aD
贡献符号相反。
如果B!=D 还会加上 vB+vD的贡献
按照这种讨论在分块里各种暴力瞎搞二分就好了。。
然后最后再把BD所在的块暴力重建就做完了。。
/* http://www.cnblogs.com/karl07/ */
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std; #define ll long long
#define lowbit(x) (x&-x)
const int N=1e5+;
const int P=1e9+;
const int MX=1e5;
int n,m,cnt;
int pos[N],st[N];
ll bit[N],bb[N];
ll lst=;
struct data{
int x,y;
}a[N],b[N]; bool oper(data a,data b){
return a.x<b.x;
} void modify(int i){
for (int j=st[i];j<st[i+];j++){
b[j].x=a[j].x;
b[j].y=a[j].y;
}
sort(b+st[i],b+st[i+],oper);
for (int j=st[i]+;j<st[i+];j++){
b[j].y=(b[j].y+b[j-].y)%P;
}
} int find(int l,int r,int x){
int mid=(l+r)/,ans=l-;
while (l<=r){
mid=(l+r)/;
if (b[mid].x<x){
ans=mid;
l=mid+;
}else{
r=mid-;
}
}
return ans;
} ll query(int x,int mn,int mx,int ny,int xy){
int p1=find(st[x],st[x+]-,mx),p2=find(st[x],st[x+]-,mn);
ll ans=;
ans+=(b[p1].y)*(p1>=st[x])+(p1-st[x]+)*xy%P;
ans+=b[st[x+]-].y-b[p2].y*(p2>=st[x])+ny*(st[x+]--p2)%P;
swap(p1,p2);
ans-=(b[p1].y)*(p1>=st[x])+(p1-st[x]+)*ny%P;
ans-=b[st[x+]-].y-b[p2].y*(p2>=st[x])+xy*(st[x+]--p2)%P;
return ans%P;
} void build(){
int sz=sqrt(n)/;
for (int i=;i<=n;i++){
if (sz== || i%sz==){
st[++cnt]=i;
}
pos[i]=cnt;
}
st[cnt+]=n+;
for (int i=;i<=cnt;i++){
modify(i);
}
} void Modify(int x,int y){
while (x<=MX){
bit[x]+=y;
bb[x]++;
bit[x]%=P;
x+=lowbit(x);
}
} ll Query(int x,int y){
ll ans=,a2=;
while (x){
ans+=bit[x];
a2+=bb[x];
ans%=P;
x-=lowbit(x);
}
ans+=a2*y%P;
return ans%P;
} int main(){
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++){
scanf("%d%d",&a[i].x,&a[i].y);
}
for (int j=;j<=n;j++){
lst+=Query(MX,a[j].y)-Query(a[j].x,a[j].y);
lst%=P;
Modify(a[j].x,a[j].y);
}
build();
for (int i=;i<=m;i++){
int x,y,x1,y1,px,py,mn,mx,ny,xy;
ll ans=;
scanf("%d%d",&x1,&y1);
x=min(x1,y1);
y=max(x1,y1);
px=pos[x],py=pos[y];
if (a[x].x<a[y].x) mn=a[x].x,ny=a[x].y,mx=a[y].x,xy=a[y].y;
else mx=a[x].x,xy=a[x].y,mn=a[y].x,ny=a[y].y;
if (px!=py){
for (int i=x+;i<st[px+];i++){
ans+= (a[i].x>mn)*(a[i].y+ny);
ans+= (a[i].x<mx)*(a[i].y+xy); ans-= (a[i].x<mn)*(a[i].y+ny);
ans-= (a[i].x>mx)*(a[i].y+xy);
ans%=P;
}
for (int i=st[py];i<y;i++){
ans+= (a[i].x>mn)*(a[i].y+ny);
ans+= (a[i].x<mx)*(a[i].y+xy); ans-= (a[i].x<mn)*(a[i].y+ny);
ans-= (a[i].x>mx)*(a[i].y+xy);
ans%=P; }
for (int i=px+;i<=py-;i++){
ans+= query(i,mn,mx,ny,xy);
ans%=P;
}
}else{
for (int i=x+;i<y;i++){
ans+= (a[i].x>mn)*(a[i].y+ny);
ans+= (a[i].x<mx)*(a[i].y+xy); ans-= (a[i].x<mn)*(a[i].y+ny);
ans-= (a[i].x>mx)*(a[i].y+xy);
}
ans%=P; }
if (x!=y) ans+=a[x].y+a[y].y;
ans%=P;
if (a[x].x>a[y].x) ans=(-ans+P)%P;
printf("%lld\n",lst=(lst+ans+P)%P);
swap(a[x],a[y]);
modify(pos[x]);
modify(pos[y]);
}
return ;
}
另外当块的大小取sqrt(n)/2的时候跑的飞快。。
40s就跑出来了。。竟然有rank5(2017.5.27)。。而且空间也很小有没有。。
【bzoj4889】: [Tjoi2017]不勤劳的图书管理员 分块-BIT的更多相关文章
- 【BZOJ4889】[Tjoi2017]不勤劳的图书管理员 分块+树状数组
[BZOJ4889][Tjoi2017]不勤劳的图书管理员 题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让 ...
- [P3759][TJOI2017]不勤劳的图书管理员(分块+树状数组)
题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生 这两本书页数的和的厌烦度.现在有n本被打乱顺序的书 ...
- [bzoj4889] [Tjoi2017]不勤劳的图书管理员
Description 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被 ...
- bzoj4889: [Tjoi2017]不勤劳的图书管理员(树套树)
传送门 据说正解线段树套平衡树 然而网上参考(抄)了一个树状数组套动态开点线段树的 思路比较清楚,看代码应该就明白了 //minamoto #include<iostream> #incl ...
- 【BZOJ4889】不勤劳的图书管理员(树套树)
[BZOJ4889]不勤劳的图书管理员(树套树) 题面 又是权限题,烦死了 洛谷真好 题解 分开考虑每一次交换产生的贡献. 假设交换\((x,y)\) 检查\(x\)与\(y\)对于区间\([x+1, ...
- 洛谷P3759 - [TJOI2017]不勤劳的图书管理员
Portal Description 给出一个\(1..n(n\leq5\times10^4)\)的排列\(\{a_n\}\)和数列\(\{w_n\}(w_i\leq10^5)\),进行\(m(m\l ...
- 【loj2639】[Tjoi2017]不勤劳的图书管理员
#2639. 「TJOI2017」不勤劳的图书管理员 题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产 ...
- 【bzoj4889】[Tjoi2017]不勤劳的图书管理员 树状数组+分块+二分
题目描述(转自洛谷) 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打 ...
- BZOJ4889 & 洛谷3759:[TJOI2017]不勤劳的图书管理员——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4889 https://www.luogu.org/problemnew/show/P3759 加里 ...
随机推荐
- 146. LRU Cache (List, HashTable)
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- 如果习惯VisualStudio,可以如下实现.Shader文件的语法高亮。
如果习惯VisualStudio,可以如下实现.Shader文件的语法高亮. 下载作者donaldwu自己添加的关键词文件usertype.dat.其包括了Unity ShaderLab的部分关键字, ...
- SUSE Linux 多路径软件+LVM+裸设备的配置
1.先要查出光纤卡的WWN号,SUSE 10下光纤卡的WWD在/sys/class/fc_host/host5/port_name文件中,有两块卡就会有两个host*的目录 接好光纤后可以在dev下可 ...
- loadrunner添加load generator连接失败解决办法
1.到防火墙设置里面“允许程序和功能通过windows防火墙”,然后添加Loadrunner Agent Procss,到列表中,在“专用”和“公用”打勾,然后重启一下LR和Loadrunner Ag ...
- 数字图像处理:基于MATLAB的车牌识别项目 标签: 图像处理matlab算法 2017-06-24 09:17 98人阅读 评论(0)
学过了数字图像处理,就进行一个综合性强的小项目来巩固一下知识吧.前阵子编写调试了一套基于MATLAB的车牌识别的项目的代码.今天又重新改进了一下代码,识别的效果好一点了,也精简了一些代码.这里没有使用 ...
- Java泛型中的通配符
Java泛型中的通配符可以直接定义泛型类型的参数.而不用把该函数定义成泛型函数. public class GenericsTest { public static void main(String[ ...
- CNN和GAN 比较nice的介绍
CNN是个什么鬼:https://www.zhihu.com/question/52668301 就是这样GAN : https://zhuanlan.zhihu.com/p/27199954
- Spring思维导图(IOC篇)
写在前面 写过java的都知道:所有的对象都必须创建:或者说:使用对象之前必须先创建.而使用ioc之后,你就可以不再手动创建对象,而是从ioc容器中直接获取对象. 就好像我们无需考虑对象的销毁回收一样 ...
- 线段树 - 3264 Balanced Lineup
大略的的看了线段树的定义然后就开始练手, 可能很多地方可以优化, 仅供参考. 徘徊在AC的边缘, 提交代码要把cout/cin 缓存 printf/scanf 刚好能过. #include <i ...
- mysql 添加字段,修改字段的用法
1.添加字段 ALTER TABLE 表明 add 字段名称 类型(int,char,VARCHAR...) DEFAULT 默认值 位置(FIRST, AFTER+字段名称); 2.删除 ALTE ...