Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)
4 seconds
512 megabytes
standard input
standard output
Anton likes permutations, especially he likes to permute their elements. Note that a permutation of n elements is a sequence of numbers {a1, a2, ..., an}, in which every number from 1 to n appears exactly once.
One day Anton got a new permutation and started to play with it. He does the following operation q times: he takes two elements of the permutation and swaps these elements. After each operation he asks his friend Vanya, how many inversions there are in the new permutation. The number of inversions in a permutation is the number of distinct pairs (i, j) such that 1 ≤ i < j ≤ n and ai > aj.
Vanya is tired of answering Anton's silly questions. So he asked you to write a program that would answer these questions instead of him.
Initially Anton's permutation was {1, 2, ..., n}, that is ai = i for all i such that 1 ≤ i ≤ n.
The first line of the input contains two integers n and q (1 ≤ n ≤ 200 000, 1 ≤ q ≤ 50 000) — the length of the permutation and the number of operations that Anton does.
Each of the following q lines of the input contains two integers li and ri (1 ≤ li, ri ≤ n) — the indices of elements that Anton swaps during the i-th operation. Note that indices of elements that Anton swaps during the i-th operation can coincide. Elements in the permutation are numbered starting with one.
Output q lines. The i-th line of the output is the number of inversions in the Anton's permutation after the i-th operation.
5 4
4 5
2 4
2 5
2 2
1
4
3
3
2 1
2 1
1
6 7
1 4
3 5
2 3
3 3
3 6
2 1
5 1
5
6
7
7
10
11
8
Consider the first sample.
After the first Anton's operation the permutation will be {1, 2, 3, 5, 4}. There is only one inversion in it: (4, 5).
After the second Anton's operation the permutation will be {1, 5, 3, 2, 4}. There are four inversions: (2, 3), (2, 4), (2, 5) and (3, 4).
After the third Anton's operation the permutation will be {1, 4, 3, 2, 5}. There are three inversions: (2, 3), (2, 4) and (3, 4).
After the fourth Anton's operation the permutation doesn't change, so there are still three inversions.
【分析】题意很简单,就是动态的求区间逆序数。当时没做出来,赛后看了题解,学了发树状数组套主席树(内层主席树外层树状数组)学了一上午=_=借这个题好好说一下我对这个的理解吧,有啥不对的希望大佬能指出来OTZ.
主席树套树状数组就是梳妆数组的每一个节点都是一颗主席树,可以理解为线段树吧。主席树可以静态的求出排名,而动态的可以借助树状数组求,logn。而对于每一棵主席树,从i~n一棵一棵的建,可以这么理解,其实每一棵树都是一样的,包括所有的节点,只是有些节点隐藏起来了,只显现了一部分,显现了哪些部分呢?这就要考虑到树状数组了。树状数组的每一个节点,都与一个lowbit有关,刷过树状数组的应该知道,见下图

比如说对于4节点,(对于这个题目)初始就只显现了1~4区间的值。而对于6节点就之显现了5~6节点,注意,我这里说的是初始阶段。好嘞,现在来说修改。比如说我要把num[2]和num[6]换一下,那我们就把第二个节点的num[6]点亮(即显现),怎么点亮了?注意,我们一开始是按照从小到大的顺序存的,即每一刻主席树的叶子节点(包括未显现的)从左到右-->从小到大,那么就可以在lson,rson里找了,复杂度logn。找到之后就点亮,sz[]++.然后往上lowbit,将所有与之相关的节点的主席树相关位置都做同样的修改,复杂度logn。现在说查询,树状数组的查询会吧,就是lowbit求前缀和嘛,这个也一样,从上往下求lowbit前缀。对于每一刻主席树,先找到这个值,然后这个值(叶子节点)左边的叶子节点个数即是这棵书中比他小的,然后把所有相关的lowbit节点的线段树(不重合)的所有比他小的值得个数加起来,logn*logn。
嗯。。。这差不多就是我的理解了,要是有啥不对的,请大佬一定要指出来呀,嘻嘻。。。
听说还有一种叫 分块 的东西比这个简单,明天就学,学会了再写个做法,嘻嘻。。。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
using namespace std;
typedef long long ll;
const int N = 2e7+;
int sz[N],lson[N],rson[N],num[N],bit[N],n,total;
int addson() {return ++total;}
int lowbit(int x) {return x&(-x);}
void add(int &x,int l,int r,int y,int z){
if (!x)x=addson();
sz[x]+=z;
if (l==r) return;
int mid=(l+r)>>;
if (y<=mid) add(lson[x],l,mid,y,z);
else add(rson[x],mid+,r,y,z);
}
int ask(int x,int l,int r,int y){
if (!x) return ;
if (l==r) return sz[x];
int mid=(l+r)>>;
if (y<=mid) return ask(lson[x],l,mid,y);
else return sz[lson[x]]+ask(rson[x],mid+,r,y);
}
ll bigask(int x,int y){
ll now=;
while (x) {
now+=ask(bit[x],,n,y);
x-=lowbit(x);
}
return now;
}
void bigadd(int x,int y,int z){
while (x<=n) {
add(bit[x],,n,y,z);
x+=lowbit(x);
}
}
int main(){
int m;
scanf("%d%d",&n,&m);
ll sum=;
for(int i=;i<=n;i++)bigadd(i,num[i]=i,);
while (m--) {
int l,r;
scanf("%d %d",&l,&r);
if (l==r) {
printf("%lld\n",sum);
continue;
}
if (l>r)swap(l,r);
if (r-l>) {
sum-=*(bigask(r-,num[l])-bigask(l,num[l]));
sum+=*(bigask(r-,num[r])-bigask(l,num[r]));
}
if (num[l]<num[r]) ++sum;
else --sum;
printf("%lld\n",sum);
bigadd(l,num[l],-);
bigadd(l,num[r],);
bigadd(r,num[r],-);
bigadd(r,num[l],);
swap(num[l],num[r]);
}
return ;
}
Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)的更多相关文章
- Codeforces Round #404 (Div. 2) D. Anton and School - 2 数学
D. Anton and School - 2 题目连接: http://codeforces.com/contest/785/problem/D Description As you probabl ...
- Codeforces Round #404 (Div. 2) C. Anton and Fairy Tale 二分
C. Anton and Fairy Tale 题目连接: http://codeforces.com/contest/785/problem/C Description Anton likes to ...
- Codeforces Round #404 (Div. 2) B. Anton and Classes 水题
B. Anton and Classes 题目连接: http://codeforces.com/contest/785/problem/B Description Anton likes to pl ...
- Codeforces Round #404 (Div. 2) A - Anton and Polyhedrons 水题
A - Anton and Polyhedrons 题目连接: http://codeforces.com/contest/785/problem/A Description Anton's favo ...
- 【组合数】【乘法逆元】 Codeforces Round #404 (Div. 2) D. Anton and School - 2
http://codeforces.com/blog/entry/50996 官方题解讲得很明白,在这里我复述一下. 枚举每个左括号,考虑计算一定包含其的简单括号序列的个数,只考虑其及其左侧的左括号, ...
- Codeforces Round #404 (Div. 2) D. Anton and School - 2
题目链接 转自 给你一个字符串问你能构造多少RSBS. #include<bits/stdc++.h> #define LL long long #define fi first #def ...
- 【二分】Codeforces Round #404 (Div. 2) C. Anton and Fairy Tale
当m>=n时,显然答案是n: 若m<n,在第m天之后,每天粮仓减少的量会形成等差数列,只需要二分到底在第几天,粮仓第一次下降到0即可. 若直接解不等式,可能会有误差,需要在答案旁边扫一下. ...
- Codeforces 605D - Board Game(树状数组套 set)
Codeforces 题目传送门 & 洛谷题目传送门 事实上是一道非常容易的题 很容易想到如果 \(c_i\geq a_j\) 且 \(d_i\geq b_j\) 就连一条 \(i\to j\ ...
- 贪心 Codeforces Round #288 (Div. 2) B. Anton and currency you all know
题目传送门 /* 题意:从前面找一个数字和末尾数字调换使得变成偶数且为最大 贪心:考虑两种情况:1. 有偶数且比末尾数字大(flag标记):2. 有偶数但都比末尾数字小(x位置标记) 仿照别人写的,再 ...
随机推荐
- 【算法】最小乘积生成树 & 最小乘积匹配 (HNOI2014画框)
今天考试的时候果然题目太难于是我就放弃了……转而学习了一下最小乘积生成树. 最小乘积生成树定义: (摘自网上一篇博文). 我们主要解决的问题就是当k = 2时,如何获得最小的权值乘积.我们注意到一张图 ...
- [LG4890]Never·island DP
---题面--- 题解: 感到此题非常的神奇...看了大佬的题解才懂的. 首先建模: 先把所有队伍的出去回来时间都放在一个数组里,然后排序,从左到右扫一边,给每个队伍都建一个带权点,进行如下操作: ( ...
- [NOIP2017]列队 线段树
---题面--- 题解: 之前写的splay,,,然而一直没调出来,我感觉是某个细节想错了,,然而已经重构4次代码不想再写splay了.于是今天尝试了线段树的解法. 首先因为每次出列之后的变化都是将当 ...
- 【bzoj2064】分裂【压状dp】
Description 背景: 和久必分,分久必和... 题目描述: 中国历史上上分分和和次数非常多..通读中国历史的WJMZBMR表示毫无压力. 同时经常搞OI的他把这个变成了一个数学模型. 假设中 ...
- BZOJ5322 [Jxoi2018]排序问题 【贪心】
题目链接 BZOJ5322 题解 意思就是使有序的排列尽量少 就是使相同的数尽量少 然后大力贪心即可 #include<algorithm> #include<iostream> ...
- CF762E Radio Stations
题目戳这里. 我还以为是KDtree呢,但是KDtree应该也可以做吧. 这是一道数据结构好题.考虑到由于\(K \le 10\),所以我们用两个大vector--\(Left,Right\),\(L ...
- Android中代码设置RadioButton的高端技巧
不知道怎么起标题,就这样了. 目前主要讲两个方面内容: 代码方式 设置RadioButton的 android:button . android:background 等属性为 @null : 代码方 ...
- CVPR2014 Objectness 源码转换(完整版) VS2012 X64 –>win32
一.版本转换 1.将源码中vs2012 X64版本转换为vs2012 win32版本. 2.源码下载及其相关资料下载http://mmcheng.net/zh/bing/ 3.需要下载源码(Pape ...
- jw player学习笔记----跨域请求
需求来源:播放器皮肤文件请求不到,被限制了. 参考官网解决方案: http://www.longtailvideo.com/support/jw-player/28844/crossdomain-fi ...
- sublime2创建一个html5的snippets文件
背景:跟了一个网上课程,老师哗啦啦敲代码,屏幕上只敲了几个字,键盘一操作,瞬间一大溜代码,看得我心惊肉跳连忙暂停抄抄抄. 举个简单的例子,我需要创建一个html文件.但是我不想每次都敲固定的格式.那么 ...