题目链接

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. JavaScript 字符串实用常用操作

    字符串截取1. substring()xString.substring(start,end)substring()是最常用到的字符串截取方法,它可以接收两个参数(参数不能为负值),分别是要截取的开始 ...

  2. App.config和Web.config配置文件的自定义配置节点

    前言 昨天修改代码发现了一个问题,由于自己要在WCF服务接口中添加了一个方法,那么在相应调用的地方进行更新服务就可以了,不料意外发生了,竟然无法更新.左查右查终于发现了问题.App.config配置文 ...

  3. UIlabel添加背景图片

    做UI的时候我们可能想给某个Label添加一个背景图片,但查看的时候会发现好像只有设置背景颜色的方法,不过我们也可以通过这种方式来解决: UIColor *color = [UIColor color ...

  4. C++自定义命名空间

    关于C++自定义命名空间,今天验证了一下命名空间如何使用,和嵌套命名空间以及出现的bug. 如何自定义命名空间,实例如下: insertion_sort.h和insertion_sort.cpp #p ...

  5. poj 2001 Shortest Prefixes

    字典树的简单应用. #include<stdio.h> #include<string.h> ][]; struct node{ int cnt; node *next[]; ...

  6. CentOS 配置防火墙操作实例(启、停、开、闭端口)CentOS Linux-FTP/对外开放端口(接口)TomCat相关

    链接地址:http://blog.csdn.net/jemlee2002/article/details/7042991 CentOS 配置防火墙操作实例(启.停.开.闭端口): 注:防火墙的基本操作 ...

  7. leetcode Letter Combinations of a Phone Number python

    class Solution(object): def letterCombinations(self, digits): """ :type digits: str : ...

  8. Linux简介(好!)

    Linux操作系统介绍 来源:233网校论文中心[ 2009-12-02 14:23:00 ]阅读:1作者:王长青编辑:studa20 [摘 要]文章从Unix.Minix系统的产生引出了Linux操 ...

  9. javascript事件小结(事件处理程序方式)--javascript高级程序设计笔记

    1.事件流:描述的是从页面中接收事件的顺序. 2.事件冒泡:IE的事件流叫做事件冒泡,即事件开始从具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到不具体的节点(文档). 3.事件捕获 ...

  10. redis的内部实现机制

    一 理论基础 redis