【分块】【树套树】bzoj2141 排队
考虑暴力更新的情况,设swap的是L,R位置的数。
swap之后的逆序对数应该等于:
之前的逆序对数
+[L+1,R-1]中比 L位置的数 大的数的个数
-[L+1,R-1]中比 L位置的数 小的数的个数
-[L+1,R-1]中比 R位置的数 大的数的个数
+[L+1,R-1]中比 R位置的数 小的数的个数
并且若L位置的数>R位置的数,逆序对数--;反之,逆序对数++。
分块,对每个块内部进行sort,这样可以二分,在O(log(sqrt(n))的时间内求得某个块内比某个数大/小的数的个数。所以每次更新是O(sqrt(n)*log(sqrt(n))的。
若L和R所在的块相同或相邻时,直接暴力更新即可。
要用树状数组或归并排序求得初始答案。
要注意数据是可重的,所以要打时间戳。
所以为了lower_bound/upper_bound,要定义两套比较法则,一套双关键字,一套单关键字。
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
struct Point{int v,p;Point(const int &a,const int &b){v=a;p=b;}Point(){}};
bool operator < (const Point &a,const Point &b){return a.v<b.v;}//单关键字比较
bool operator > (const Point &a,const Point &b){return a.v>b.v;}
bool operator == (const Point &a,const Point &b){return a.v==b.v ? true : false;}
bool cmp(const Point &a,const Point &b){return a.v!=b.v ? a.v<b.v : a.p<b.p;}//双关键字比较
Point b[],a[],c[];
int n,sz,l[],r[],sum,num[],ans,x,y,m,mid,en;
int Res,Num;char C,CH[];
inline int G()
{
Res=;C='*';
while(C<''||C>'')C=getchar();
while(C>=''&&C<=''){Res=Res*+(C-'');C=getchar();}
return Res;
}
inline void P(int x)
{
if(!x){putchar('');putchar('\n');return;}
Num=;while(x>)CH[++Num]=x%,x/=;
while(Num)putchar(CH[Num--]+);
putchar('\n');
}
void LiSan()
{
n=G();
for(int i=;i<=n;i++){b[i].v=G();b[i].p=i;}
sort(b+,b+n+,cmp);
for(int i=;i<=n;i++)
{
if(b[i].v!=b[i-].v)en++;
a[b[i].p].v=en;
a[b[i].p].p=i;
}
}
//树状数组求出初始答案。
int D[];inline int lowbit(const int &x){return x&(-x);}
inline int getsum(int x){int res=;while(x>){res+=D[x];x-=lowbit(x);}return res;}
inline void add(int x,const int &d){while(x<=n){D[x]+=d;x+=lowbit(x);}}
void Get_First_Ans()
{for(int i=;i<=n;i++){add(a[i].v,);ans+=(i-getsum(a[i].v));}
P(ans);}
void makeblock()
{
sz=sqrt(n);
for(sum=;sum*sz<n;sum++)
{
l[sum]=(sum-)*sz+;r[sum]=sum*sz;
for(int i=l[sum];i<=r[sum];i++)
num[i]=sum;
}
l[sum]=sz*(sum-)+;r[sum]=n;
for(int i=l[sum];i<=r[sum];i++)
num[i]=sum;
}
void Sort_Each_Block()
{for(int i=;i<=n;i++)c[i]=a[i];
for(int i=;i<=sum;i++)sort(a+l[i],a+r[i]+,cmp);}
inline int Query(const int &L,const int &R)
{
swap( a[lower_bound(a+l[num[L]],a+r[num[L]]+,c[L],cmp) - a ]
, a[lower_bound(a+l[num[R]],a+r[num[R]]+,c[R],cmp)- a ]);//必须双关键字比较
sort(a+l[num[L]],a+r[num[L]]+,cmp);
sort(a+l[num[R]],a+r[num[R]]+,cmp);
int cnt=;
if(c[L].v<c[R].v)cnt=;
else if(c[L].v>c[R].v)cnt=-;
swap(c[L],c[R]);
if(num[L]+>=num[R])
for(int i=L+;i<=R-;i++)
{if(c[i].v>c[R].v)cnt++;else if(c[i].v<c[R].v)cnt--;
if(c[i].v>c[L].v)cnt--;else if(c[i].v<c[L].v)cnt++;}
else
{
for(int i=L+;i<=r[num[L]];i++)
{if(c[i].v>c[R].v)cnt++;else if(c[i].v<c[R].v)cnt--;
if(c[i].v>c[L].v)cnt--;else if(c[i].v<c[L].v)cnt++;}
for(int i=l[num[R]];i<=R-;i++)
{if(c[i].v>c[R].v)cnt++;else if(c[i].v<c[R].v)cnt--;
if(c[i].v>c[L].v)cnt--;else if(c[i].v<c[L].v)cnt++;}
for(int i=num[L]+;i<=num[R]-;i++)
{
cnt+=( (a+r[i]+) - upper_bound(a+l[i],a+r[i]+,c[R]) );//必须单关键字比较
cnt-=( lower_bound(a+l[i],a+r[i]+,c[R]) - (a+l[i]) );
cnt-=( (a+r[i]+) - upper_bound(a+l[i],a+r[i]+,c[L]) );
cnt+=( lower_bound(a+l[i],a+r[i]+,c[L]) - (a+l[i]) );
}
}
ans+=cnt;return ans;
}
int main()
{
LiSan();Get_First_Ans();makeblock();Sort_Each_Block();m=G();
for(int i=;i<=m;i++){x=G();y=G();if(x>y)swap(x,y);P(Query(x,y));}
return ;
}
【分块】【树套树】bzoj2141 排队的更多相关文章
- 【BZOJ2141】排队(树套树)
[BZOJ2141]排队(树套树) 题面 BZOJ 洛谷 题解 傻逼题啊... 裸的树套树 树状数组套线段树,每次交换的时候,考虑一下前后的贡献,先删掉贡献,再重新算一遍就好了.. #include& ...
- [BZOJ 3720][JZYZOJ 2016]gty的妹子树 强制在线 树分块/树套树
jzyzoj的p2016 先码着,强制在线的树分块或者树套树?关键是我树分块还在入门阶段树套树完全不会啊摔 http://blog.csdn.net/jiangyuze831/article/de ...
- [BZOJ3236][AHOI2013]作业:树套树/莫队+分块
分析 第一问随便搞,直接说第二问. 令原数列为\(seq\),\(pre_i\)为\(seq_i\)这个值上一个出现的位置,于是可以简化询问条件为: \(l \leq i \leq r\) \(a \ ...
- 树套树Day1线段树套平衡树bzoj3196
您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查 ...
- [luogu2617][bzoj1901][Zju2112]Dynamic Rankings【树套树+树状数组+主席树】
题目网址 [传送门] 题目大意 请你设计一个数据结构,支持单点修改,区间查询排名k. 感想(以下省略脏话inf个字) 真的强力吹爆洛谷数据,一般的树套树还给我T了一般的点,加强的待修主席树还给我卡了几 ...
- 洛谷P4396 [AHOI2013]作业(树套树)
题意 题目链接 Sol 为什么一堆分块呀..三维数点不应该是套路离线/可持久化+树套树么.. 亲测树状数组套权值线段树可过 复杂度\(O(nlog^2n)\),空间\(O(nlogn)\)(离线) # ...
- BZOJ 3110: [Zjoi2013]K大数查询 [树套树]
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6050 Solved: 2007[Submit][Sta ...
- BZOJ4170 极光(CDQ分治 或 树套树)
传送门 BZOJ上的题目没有题面-- [样例输入] 3 5 2 4 3 Query 2 2 Modify 1 3 Query 2 2 Modify 1 2 Query 1 1 [样例输出] 2 3 3 ...
- bzoj3262: 陌上花开(树套树)
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...
- bzoj3295: [Cqoi2011]动态逆序对(树套树)
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...
随机推荐
- bzoj 1034 贪心
首先如果我们想取得分最高的话,肯定尽量赢,实在赢不了的话就耗掉对方最高的,那么就有了贪心策略,先排序,我方最弱的马和敌方最弱的相比,高的话赢掉,否则耗掉敌方最高的马. 对于一场比赛,总分是一定的,所以 ...
- 对象方法、类方法、原型方法 && 私有属性、公有属性、公有静态属性
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- 各浏览器的Hack写法【转】
Hack是针对不同的浏览器去写不同的CSS样式,从而让各浏览器能达到一致的渲染效果,那么针对不同的浏览器写不同的CSS CODE的过程,就叫CSS HACK,同时也叫写CSS Hack.然后将Hack ...
- java封装示例代码
package com.imooc; public class Telphone { private float screen; private float cpu; private float me ...
- 【hihocoder】sam-2
原意是把sam那一堆做完…… 这题还是很sb的,$\sum{maxlen(s)-minlen(s)+1}$就是本质不同的子串数量 然后因为suffix link的性质,maxlen[fa[s]]=mi ...
- [Deep dig] ViewController初始化过程调查
代码:https://github.com/xufeng79x/ViewControllerLife 1.简介: 介绍xib方式.storyborad方式以及code方式下ViewController ...
- An In-Depth Look at the HBase Architecture
https://www.mapr.com/blog/in-depth-look-hbase-architecture An In-Depth Look at the HBase Architectur ...
- Redis 基础使用(1)
redis 数据库的使用场景介绍 redis 是 NoSQL 数据库中的一种,特别适合解决一些使用传统关系数据库难以解决的问题,redis 作为内存数据库,如果在不合适的场合,对内存的消耗是很大的,甚 ...
- 手机端GPS定位结合百度地图实现定位
html页面: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Typ ...
- Django基础之form组件
Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否 ...