【分块】【树套树】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 1588 bst
用set存下就好了. /************************************************************** Problem: 1588 User: BLADE ...
- VMware Workstation Pro 14 序列号
VMware Workstation Pro 14 序列号: AA702-81D8N-0817Y-75PQT-Q70A4 YC592-8VF55-M81AZ-FWW5T-WVRV0 FC78K-FKE ...
- Python 开发中easy_install的安装及使用
easy_install是一个python的扩展包,主要是用来简化python安装第三方安装包,在安装了easy_install之后,安装python第三方安装包就只需要在命令行中输入:easy_in ...
- 完全教程 Aircrack-ng破解WEP、WPA-PSK加密利器
其 实关于无线基础知识的内容还是挺多的,但是由于本书侧重于BT4自身工具使用的讲解,若是再仔细讲述这些外围的知识,这就好比讲述DNS工具时还要把 DNS服务器的类型.工作原理及配置讲述一遍一样,哈哈, ...
- python基础===requests学习笔记
这里有一个新的学习requests网站:http://docs.python-requests.org/zh_CN/latest/user/quickstart.html2017/11/30 Requ ...
- ogre 3d游戏开发框架指南
ogre 3d游戏开发框架指南pdf 附光盘代码 http://www.ddooo.com/softdown/74228.htm OGRE3D游戏开发框架指南.pdf http://vdisk.wei ...
- perl多线程tcp端口扫描器(原创)
perl多线程tcp端口扫描器(原创) http://bbs.chinaunix.net/thread-1457744-1-1.html perl socket 客户端发送消息 http://blog ...
- .NET Core、.NET Standard、Xamarin和.NET Framework对比
近日,微软发布了.NET Core 2.0,但是开发人员中间仍然存在一些疑惑,就是.NET Core..NET Standard.Xamarin和.NET Framework有什么不同. .NET F ...
- Django视图之ORM数据库查询操作API
查询表记录 查询相关API 操作:models.表名.objects.方法() all(): 查询所有结果 filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 get(**kwar ...
- SEO页面标题Title的优化
我在一个月前改过页面标题(Title),随后表现是:百度网页快照4天不更新,Google正常.而我仅仅是改了两个词组而已.在建博初期,修改Title的最频繁的时期,下面卢松松就我经历的修改Title过 ...