考虑暴力更新的情况,设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 排队的更多相关文章

  1. 【BZOJ2141】排队(树套树)

    [BZOJ2141]排队(树套树) 题面 BZOJ 洛谷 题解 傻逼题啊... 裸的树套树 树状数组套线段树,每次交换的时候,考虑一下前后的贡献,先删掉贡献,再重新算一遍就好了.. #include& ...

  2. [BZOJ 3720][JZYZOJ 2016]gty的妹子树 强制在线 树分块/树套树

    jzyzoj的p2016 先码着,强制在线的树分块或者树套树?关键是我树分块还在入门阶段树套树完全不会啊摔   http://blog.csdn.net/jiangyuze831/article/de ...

  3. [BZOJ3236][AHOI2013]作业:树套树/莫队+分块

    分析 第一问随便搞,直接说第二问. 令原数列为\(seq\),\(pre_i\)为\(seq_i\)这个值上一个出现的位置,于是可以简化询问条件为: \(l \leq i \leq r\) \(a \ ...

  4. 树套树Day1线段树套平衡树bzoj3196

    您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查 ...

  5. [luogu2617][bzoj1901][Zju2112]Dynamic Rankings【树套树+树状数组+主席树】

    题目网址 [传送门] 题目大意 请你设计一个数据结构,支持单点修改,区间查询排名k. 感想(以下省略脏话inf个字) 真的强力吹爆洛谷数据,一般的树套树还给我T了一般的点,加强的待修主席树还给我卡了几 ...

  6. 洛谷P4396 [AHOI2013]作业(树套树)

    题意 题目链接 Sol 为什么一堆分块呀..三维数点不应该是套路离线/可持久化+树套树么.. 亲测树状数组套权值线段树可过 复杂度\(O(nlog^2n)\),空间\(O(nlogn)\)(离线) # ...

  7. BZOJ 3110: [Zjoi2013]K大数查询 [树套树]

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[Submit][Sta ...

  8. 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 ...

  9. bzoj3262: 陌上花开(树套树)

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  10. bzoj3295: [Cqoi2011]动态逆序对(树套树)

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

随机推荐

  1. 20151024_002_C#基础知识(ArrayList,Hashtable,List,Dictionary)

    1:ArrayList 和 Hashtable(哈希表) 1.1:ArrayList ArrayList list = new ArrayList(); list.Add(); list.AddRan ...

  2. JavaScript字符串逆序

    如何对字符串进行倒序呢?你首先想到的方法就是生成一个栈,从尾到头依次取出字符串中的字符压入栈中,然后把栈连接成字符串. var reverse = function( str ){ var stack ...

  3. Tomcat的安装以及基本配置

    Tomcat是目前最常见也是最流行的基于java的一个web服务器软件   Tomcat的安装   (1)首先需要java环境,也就是说要依赖于java虚拟机JVM   (2)下载Tomcat ,地址 ...

  4. HTML综合实例【月福首页】

    1. 首页的布局结构 2. 排版的准备工作 网站的素材:与当前网页放在一起. 创建一个html文件,来进行排版. 网页的背景色 确定主页的宽度:778px 3. HTML注释 <!-- 注释内容 ...

  5. C++ 模板的用法

    C++中的高阶手法就会用到泛型编程,主要有函数模板, 在程序中使用模板的好处就是在定义时不需要指定具体的参数类型,而在使用时确可以匹配其它任意类型, 定义格式如下 template <class ...

  6. 如何在阿里云esc上安装wordpress

    本人的个人网纱建好,但是由于新申请的域名还没有备案 所以暂时无法通过域名访问. 1.按顺序边看边跟着做基本上你能够很优雅的完成大部分设置. http://bbs.aliyun.com/read/162 ...

  7. JDBC数据源连接池(4)---自定义数据源连接池

    [续上文<JDBC数据源连接池(3)---Tomcat集成DBCP>] 我们已经 了解了DBCP,C3P0,以及Tomcat内置的数据源连接池,那么,这些数据源连接池是如何实现的呢?为了究 ...

  8. mac date 和 Linux date实现从指定时间开始循环

    Linux date begin="2016-01-01" ; i < ; i++ )); do current=$(date -d "$i day $begin& ...

  9. Django视图之ORM连表操作一

    1 项目路径结构树 2 models创建类 from django.db import models class UserType(models.Model): ''' 用户类型 ''' title ...

  10. ceph在扩展mon节点时,要注意的问题

    我开始也是一步一步的按官方文档操作. 但后来还是遇到了问题. 当我要扩展mon节点时,死活出错. (我就一共用了三个节点ceph-admin, ceph-node1, ceph-node2) 比如: ...