题目链接

2141: 排队

Time Limit: 4 Sec  Memory Limit: 259 MB
Submit: 1169  Solved: 465
[Submit][Status][Discuss]

Description

排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足ihj的(i,j)数量。幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。

Input

第一行为一个正整数n,表示小朋友的数量;第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;第三行为一个正整数m,表示交换操作的次数;以下m行每行包含两个正整数ai和bi¬,表示交换位置ai与位置bi的小朋友。

Output

输出文件共m行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度。

Sample Input

【样例输入】
3
130 150 140
2
2 3
1 3

Sample Output

1
0
3
 
 
每次交换两个数, 求交换之后的逆序对的个数。
 
思路:  我们分块来做, 如果要交换的两个数x, y在同一块里, 那么就暴力计算。 否则的话, 暴力计算x+1到x这个块的最右边, 和y-1到y这个块的最左边, 两个块中间的块用二分查找来计算。
弱智错误查了一个小时...
 #include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-;
const int mod = 1e9+;
const int inf = ;
const int dir[][] = { {-, }, {, }, {, -}, {, } };
const int maxn = 2e4+;
int a[maxn], b[maxn], c[maxn], sum[maxn], l[maxn], r[maxn], belong[maxn];
int block, cnt, n, ans;
int lowbit(int x) {
return x&(-x);
}
void update(int x) {
for(int i = x; i<=n; i+=lowbit(i)) {
sum[i]++;
}
}
int query(int x) {
int ret = ;
for(int i = x; i>; i-=lowbit(i)) {
ret += sum[i];
}
return ret;
}
void rebuild(int x) {
for(int i = l[x]; i<=r[x]; i++)
b[i] = a[i];
sort(b+l[x], b+r[x]+);
}
void pre() {
for(int i = n; i>; i--) {
ans += query(a[i]-);
update(a[i]);
}
for(int i = ; i<=cnt; i++) {
rebuild(i);
}
}
void cmp(int x, int y) {
if(x>y)
ans++;
if(x<y) //不要写else...可能相等
ans--;
}
void solve(int x, int y) {
if(a[x]>a[y])
ans--;
if(a[x]<a[y]) //不要写else!!
ans++;
if(belong[x] == belong[y]) {
for(int i = x+; i<y; i++) {
cmp(a[i], a[x]);
cmp(a[y], a[i]);
}
} else {
for(int i = x+; i<=r[belong[x]]; i++) {
cmp(a[i], a[x]);
cmp(a[y], a[i]);
}
for(int i = l[belong[y]]; i<y; i++) {
cmp(a[i], a[x]);
cmp(a[y], a[i]);
}
for(int i = belong[x]+; i<belong[y]; i++) {
ans -= lower_bound(b+l[i], b+r[i]+, a[x])-b--l[i];
ans += lower_bound(b+l[i], b+r[i]+, a[y])-b--l[i];
ans -= r[i] - (upper_bound(b+l[i], b+r[i]+, a[y])-b-l[i]);
ans += r[i] - (upper_bound(b+l[i], b+r[i]+, a[x])-b-l[i]);
}
}
swap(a[x], a[y]);
rebuild(belong[x]);
rebuild(belong[y]);
}
int main()
{
int m;
cin>>n;
block = sqrt(1.0*n);
if(n%block)
cnt = n/block+;
else
cnt = n/block;
for(int i = ; i<=cnt; i++) {
l[i] = (i-)*block+;
r[i] = i*block;
}
r[cnt] = n;
for(int i = ; i<=n; i++) {
scanf("%d", &a[i]);
c[i-] = a[i];
belong[i] = (i-)/block+;
}
sort(c, c+n);
int tmp = unique(c, c+n)-c;
for(int i = ; i<=n; i++) {
a[i] = b[i] = lower_bound(c, c+tmp, a[i])-c+;
}
pre();
cout<<ans<<endl;
cin>>m;
while(m--) {
int x, y;
scanf("%d%d", &x, &y);
if(x>y)
swap(x, y);
solve(x, y);
printf("%d\n", ans);
}
return ;
}

bzoj 2141 : 排队 分块的更多相关文章

  1. Bzoj 2141: 排队 分块,逆序对,树状数组

    2141: 排队 Time Limit: 4 Sec  Memory Limit: 259 MBSubmit: 1310  Solved: 517[Submit][Status][Discuss] D ...

  2. bzoj 2141: 排队

    2141: 排队 Time Limit: 4 Sec Memory Limit: 259 MB Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我, ...

  3. BZOJ 2141 排队(分块+树状数组)

    题意 第一行为一个正整数n,表示小朋友的数量:第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高:第三行为一个正整数m,表示交换操作的次数:以下m行每行包含两个正整数 ...

  4. BZOJ 2141: 排队 [CDQ分治]

    题意: 交换序列中两个元素,求逆序对 做分块做到这道题...一看不是三维偏序嘛.... 作为不会树套树的蒟蒻就写CDQ分治吧.... 对时间分治...x排序...y树状数组... 交换拆成两个插入两个 ...

  5. bzoj 2141 : 排队 (cdq分治+bit)

    链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2141 思路: 其实就是求动态逆序对...cdq降维,用树状数组前后求两遍逆序对就好了 切水 ...

  6. BZOJ 2141 排队(树状数组套treap)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2141 题意:给出一个数列A,每次交换两个数的位置.输出交换后逆序对的个数. 思路:首先, ...

  7. BZOJ 2141 排队 (CDQ分治)

    [BZOJ2141]排队 这道题和动态逆序对比较像(BZOJ-3295 没做过的同学建议先做这题),只是删除操作变成了交换.解法:交换操作可以变成删除加插入操作,那么这题就变成了 (时间,位置,值)的 ...

  8. BZOJ 2141 排队(树状数组套主席树)

    解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...

  9. BZOJ - 2141 排队 (动态逆序对,区间线段树套权值线段树)

    题目链接 交换两个数的位置,只有位于两个数之间的部分会受到影响,因此只需要考虑两个数之间有多少数对a[l]和a[r]产生的贡献发生了变化即可. 感觉像是个带修改的二维偏序问题.(修改点$(x,y)$的 ...

随机推荐

  1. html系列教程--DOCTYPE a area

    <!DOCTYPE>标签:<!DOCTYPE> 声明不是 HTML 标签:它是指示 web 浏览器关于页面使用哪个 HTML 版本进行编写的指令.在 HTML 4.01 中,& ...

  2. C# datetimePicker控件格式设置

    //必须先设置Format属性为Custom,然后才能自定义格式 this.dtPicker.Format = DateTimePickerFormat.Custom; this.dtPicker.C ...

  3. 【iOS技术】Xcode+GitHub远程代码托管(GIT, SVN)

    原创 2016-05-24 旭哥 蓝鸥 学生对旭哥的评价是这样的: 旭哥 为什么这么年轻 知识却比我们多这么多............ 旭哥很是负责,对同学的各种问题都能够热心地解答,在旭哥的带领下, ...

  4. 场景切换特效Transition——Cocos2d-x学习历程(十二)

    Transition 场景切换 在游戏中通常会用到一些场景的切换,比如从加载界面切换到欢迎界面.游戏中的所有场景存放在一个栈中,有且只有一个场景可以处于激活状态.直接replaceScene(即不适用 ...

  5. mysql utf8_bin跟utf8_general_ci的区别

    ci是 case insensitive, 即 "大小写不敏感", a 和 A 会在字符判断中会被当做一样的; bin 是二进制, a 和 A 会别区别对待. 例如你运行: SEL ...

  6. jquery 学习笔记二 隐藏与显示

    css找到元素后是添加样式,而jquery找到元素后是添加形为. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional// ...

  7. U盘装centos7系统过程

    1. 使用最新版UltraISO将ISO镜像刻录到U盘 一定要是最新版,试用版都可以,按下图操作: 2. U盘启动电脑进入安装界面 正常情况下你应该会看到下面的这个界面: 选择第一项,然后按TAB键, ...

  8. c++ containers

    顺序容器 array(C++11) vector string deque forward_list(C++11) list 容器适配器 stack queue priority_queue 关联容器 ...

  9. CSS自学笔记(2):CSS语法

    CSS的语法规则主要有两个分构成选择器和声明(声明问一条或者多条). selector {declaration1; declaration2; ... declarationN } 选择器(selc ...

  10. 你可能不知道的一些JavaScript 奇技淫巧

    这里记录一下以前学习各种书籍和文章里边出现的JS的小技巧,分享给大家,也供自己查阅,同时感谢那些发现创造和分享这些技巧的前辈和大牛们. 1.遍历一个obj的属性到数组 var a=[]; for(a[ ...