解法很多的题,可以块套树状数组,可以线段树套平衡树。我用的是树状数组套主席树。

题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数。(n,m<=2e4).

对于没有交换操作的逆序对数,可以直接用树状数组直接统计。

考虑每次交换操作(l,r),那么逆序对数会有什么变化呢。

1.如果a[l]>a[r],ans--,如果a[l]<a[r],那么ans++.

2.剩下的就是a[l]和a[r]对区间[l+1,r-1]之内数字的影响了。

ans+=([l+1,r-1]内比a[l]大的数)-([l+1,r-1]内比a[l]小的数)+([l+1,r-1]内比a[r]小的数)-([l+1,r-1]内比a[r]大的数)。

查询区间内比指定数字小或者大的数字数目,可以用主席树来实现。

现在要求支持动态交换两个数,显然用树状数组套主席树可以实现。

时间复杂度O(mlognlogn).常数略大。

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <bitset>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int N=;
//Code begin... int a[N], tree[N], ans;
int root[N], s[N*], ls[N*], rs[N*], sz, siz;
VI v; void add(int x){while (x<N) ++tree[x], x+=lowbit(x);}
int sum(int x){
int res=;
while (x) res+=tree[x], x-=lowbit(x);
return res;
}
void Update(int l, int r, int x, int &y, int L, int val){
y=++sz; s[y]=s[x]+val;
if (l==r) return ;
ls[y]=ls[x]; rs[y]=rs[x];
int mid=(l+r)>>;
if (L<=mid) Update(l,mid,ls[x],ls[y],L,val);
else Update(mid+,r,rs[x],rs[y],L,val);
}
int Query(int l, int r, int x, int L){
if (r<L) return ;
if (l>=L) return s[x];
int mid=(l+r)>>;
return Query(l,mid,ls[x],L)+Query(mid+,r,rs[x],L);
}
int Query2(int l, int r, int x, int L){
if (l>L) return ;
if (r<=L) return s[x];
int mid=(l+r)>>;
return Query2(l,mid,ls[x],L)+Query2(mid+,r,rs[x],L);
}
int Sum(int l, int x){
int res=;
while (l) res+=Query(,siz,root[l],x+), l-=lowbit(l);
return res;
}
int Sum2(int l, int x){
int res=;
while (l) res+=Query2(,siz,root[l],x-), l-=lowbit(l);
return res;
}
void Add(int x, int n, int l, int val){while (x<=n) Update(,siz,root[x],root[x],l,val), x+=lowbit(x);}
int main ()
{
int n, m, x, y;
scanf("%d",&n);
FOR(i,,n) scanf("%d",a+i), v.pb(a[i]);
sort(v.begin(),v.end());
siz=unique(v.begin(),v.end())-v.begin();
FOR(i,,n) {
a[i]=lower_bound(v.begin(),v.begin()+siz,a[i])-v.begin()+;
ans+=(i--sum(a[i])); add(a[i]);
Add(i,n,a[i],);
}
printf("%d\n",ans);
scanf("%d",&m);
while (m--) {
scanf("%d%d",&x,&y);
if (x>y) swap(x,y);
if (a[x]<a[y]) ++ans;
else if (a[x]>a[y]) --ans;
ans+=(Sum(y-,a[x])-Sum(x,a[x]))-(Sum(y-,a[y])-Sum(x,a[y]))+(Sum2(y-,a[y])-Sum2(x,a[y]))-(Sum2(y-,a[x])-Sum2(x,a[x]));
Add(x,n,a[x],-); Add(x,n,a[y],); Add(y,n,a[y],-); Add(y,n,a[x],);
swap(a[x],a[y]);
printf("%d\n",ans);
}
return ;
}

BZOJ 2141 排队(树状数组套主席树)的更多相关文章

  1. BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树

    [题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...

  2. BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树

    [题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...

  3. BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树

    BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...

  4. ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解

    题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...

  5. P2617 Dynamic Rankings(树状数组套主席树)

    P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...

  6. [COGS257]动态排名系统 树状数组套主席树

    257. 动态排名系统 时间限制:5 s   内存限制:512 MB [问题描述]给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:1.查询A[ ...

  7. 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】

    题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...

  8. Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)

    E. Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input sta ...

  9. 【Luogu】P2617Dynamic Ranking(树状数组套主席树)

    题目链接 树状数组套主席树有点难懂qwq 不好理解 树状数组套主席树的直观理解应该是:树状数组的每一个节点是一棵主席树. 普通区间修改我们是创建1个线段树,树状数组套主席树的时候我们就创建log个线段 ...

随机推荐

  1. ubuntu装openVPN会遇到的问题

    与Windows系统相比,Linux下安装OpenVPN的过程就显得有点曲折. 如果你使用的是Ubuntu系统,你可以直接使用命令sudo apt-get install -y openvpn来安装O ...

  2. WPF DataGridTable

    由于项目要显示表头合并,而数据源列随时变更,又不想重复的画表格,就实现动态数据(dynamic)绑定和配置数据列模板的方式 编辑DataGridColumnHeader样式实现表头合并:效果如下 实现 ...

  3. 一个web应用的诞生(2)--使用模板

    经过了第一章的内容,已经可以做出一些简单的页面,首先用这种方式做一个登录页面,首先要创建一个login的路由方法: @app.route("/login",methods=[&qu ...

  4. selenium自动化之定位多个元素

    前面我们讲的都是如何定位单个元素,下面讲下怎么去定位多个元素,并且输出文本. 以百度为例:获取标红的这一组元素的文本 这里我用到的是xpath来定位的://div[@id="u1" ...

  5. qt cout输出中文乱码解决记录

    工具 -> 选项-> 文本编辑器-> 行为 -> 文件编码->默认编码改为System 乱码原因: 默认用utf-8编码,控制台默认gbk编码,编码不一致导致的乱码

  6. Android 8.0 NavigationBar 颜色问题。

    1. packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java public void on ...

  7. 第八次ScrumMeeting博客

    第八次ScrumMeeting博客 本次会议于11月2日(四)22时整在3公寓725房间召开,持续20分钟. 与会人员:刘畅.辛德泰.窦鑫泽.张安澜.赵奕.方科栋. 1. 每个人的工作(有Issue的 ...

  8. angularjs工作原理解析

    个人觉得,要很好的理解AngularJS的运行机制,才能尽可能避免掉到坑里面去.在这篇文章中,我将根据网上的资料和自己的理解对AngularJS的在启动后,每一步都做了些什么,做一个比较清楚详细的解析 ...

  9. Java 通过先序中序序列生成二叉树

    题目 二叉树的前序以及后续序列,以空格间隔每个元素,重构二叉树,最后输出二叉树的三种遍历方式的序列以验证. 输入: 1 2 3 4 5 6 7 8 9 10 3 2 5 4 1 7 8 6 10 9 ...

  10. 02慕课网《vue.js2.5入门》——Vue中的组件,实现todolist

    TodoList功能开发 例子:输入字符,在列表中显示: 由于有v-for属性,<li>不会被渲染,它已经和数据绑定在一起,有数据来决定 input和button上都有事件监听器,inpu ...