【分块】【树套树】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 ...
随机推荐
- 20151024_004_C#基础知识(C#中的访问修饰符,继承,new关键字,里氏转换,is 和 as,多态,序列化与反序列化)
1:C#中的访问修饰符 public: 公共成员,完全公开,没有访问限制. private: 私有的,只能在当前类的内部访问. protected: 受保护的,只能在当前类的内部以及该类的子类中访问. ...
- javascript 事件知识集锦
1.事件委托极其应用 转载的链接: http://www.webhek.com/event-delegate/#comments 2. 解析javascript事件机制 转载链接: http: ...
- bzoj 3207 可持久化线段树
首先因为固定询问长度,所以我们可以将整个长度为n的数列hash成长度为n-k+1的数列,每次询问的序列也hash成一个数,然后询问这个数是不是在某个区间中出现过,这样我们可以根据初始数列的权值建立可持 ...
- a标签的嵌套
1.a标签的嵌套 a标签不能嵌套,若a标签中嵌套了a标签,浏览器会自动添加结束符号,故不能嵌套 2.例子 编辑器中的代码 <a href="#">外层a标签<a ...
- js中的for in 循环
1.数组 使用for in 遍历数组时,其索引被视为对象的属性,从而直接输出数组的索引 var arr = ["a","b","c"]; f ...
- 网络知识===wireshark抓包,三次握手分析
TCP需要三次握手建立连接: 网上的三次握手讲解的太复杂抽象,尝试着使用wireshark抓包分析,得到如下数据: 整个过程分析如下: step1 client给server发送:[SYN] Seq ...
- 在Github里集成Readthedocs服务
Readthedocs支持Markdown格式和sphinx格式的文档排版,是部署项目文档的绝佳平台.利用Github的托管服务,我们可以方便地将文档托管于Github,并利用Readthedocs查 ...
- ASP.NET Core学习链接
https://www.cnblogs.com/artech/p/dependency-injection-in-asp-net-core.html http://www.cnblogs.com/ar ...
- 如何生成[0,maxval]范围内m个随机整数的无重复的有序序列
在这里我们将待生成的数据结构称为IntSet,接口定义如下: class IntSetImp { public: IntSetImp(int maxelements,int maxval); void ...
- 取消div,a等标签点击效果
当标签被设置onclick事件之后,在有些手机浏览器中,点击这些标签,会有点击变色效果.想要取消点击变色效果. 添加:div{-webkit-tap-highlight-color:rgba(0,0, ...