【bzoj2141】排队 分块+树状数组
题目描述
排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足i<j且hi>hj的(i,j)数量。幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。
输入
第一行为一个正整数n,表示小朋友的数量;第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;第三行为一个正整数m,表示交换操作的次数;以下m行每行包含两个正整数ai和bi,表示交换位置ai与位置bi的小朋友。
输出
输出文件共m行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度。
样例输入
3
130 150 140
2
2 3
1 3
样例输出
1
0
3
题解
分块+树状数组
题目描述不清,这里已补好,所求即逆序对的个数。
求逆序对我们可以使用树状数组。但是树状数组是离线的,也就是说每次交换都必须重新扫一遍,这样肯定会T。
由于每次交换时,除了这两个数及它们之间的数以外都是不需要改动的,只要找出中间的即可。
我们有分块大法。
把所有元素分成√n 个块,对每个块建立一个树状数组,就可以得出两个数之间所有整块的不同范围内数的个数。
然后对于多出来的那些数,直接暴力扫一下即可。由于它们都不是整块,所以不会有超过√n 个数。
这里偷了点懒没有if else,把符合条件加加减减直接变成加减条件成立性,应该不难理解。
时间复杂度O(n*√n*logn)。
需要注意的是两个数在同一个块内的处理,以及x>y的特判。
还有,题目中可能会出现相同的数,因此不能看作非小即大,需要分开处理。
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
struct data
{
int h , p;
}a[20010];
int v[20010] , top , f[150][20010];
bool cmp1(data a , data b)
{
return a.h < b.h;
}
bool cmp2(data a , data b)
{
return a.p < b.p;
}
void update(int p , int x , int a)
{
int i;
for(i = x ; i <= top ; i += i & (-i))
f[p][i] += a;
}
int query(int p , int x)
{
int i , ans = 0;
for(i = x ; i ; i -= i & (-i))
ans += f[p][i];
return ans;
}
int main()
{
int n , m , i , j , si , ans = 0 , x , y;
scanf("%d" , &n);
si = (int)sqrt(n);
for(i = 0 ; i < n ; i ++ )
scanf("%d" , &a[i].h) , a[i].p = i;
sort(a , a + n , cmp1);
for(i = 0 ; i < n ; i ++ )
{
if(a[i].h != v[top]) v[++top] = a[i].h;
a[i].h = top;
}
sort(a , a + n , cmp2);
for(i = 0 ; i < n ; i ++ )
{
for(j = 0 ; j <= i / si ; j ++ ) ans -= query(j , a[i].h);
ans += i;
update(i / si , a[i].h , 1);
}
printf("%d\n" , ans);
scanf("%d" , &m);
while(m -- )
{
scanf("%d%d" , &x , &y);
x -- ; y -- ;
if(x > y) swap(x , y);
if(x / si == y / si)
for(i = x + 1 ; i < y ; i ++ )
ans += (a[i].h > a[x].h) + (a[i].h < a[y].h) - (a[i].h < a[x].h) - (a[i].h > a[y].h);
else
{
for(i = x / si + 1 ; i < y / si ; i ++ )
ans += (si - query(i , a[x].h)) + query(i , a[y].h - 1) - query(i , a[x].h - 1) - (si - query(i , a[y].h));
for(i = x + 1 ; i < (x / si + 1) * si ; i ++ )
ans += (a[i].h > a[x].h) + (a[i].h < a[y].h) - (a[i].h < a[x].h) - (a[i].h > a[y].h);
for(i = y / si * si ; i < y ; i ++ )
ans += (a[i].h > a[x].h) + (a[i].h < a[y].h) - (a[i].h < a[x].h) - (a[i].h > a[y].h);
}
ans += (a[x].h < a[y].h) - (a[x].h > a[y].h);
update(x / si , a[x].h , -1) , update(y / si , a[y].h , -1);
swap(a[x].h , a[y].h);
update(x / si , a[x].h , 1) , update(y / si , a[y].h , 1);
printf("%d\n" , ans);
}
return 0;
}
【bzoj2141】排队 分块+树状数组的更多相关文章
- BZOJ2141:排队(分块,树状数组)
Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们 ...
- BZOJ_2141_排队_树状数组+分块
BZOJ2141_排队_树状数组+分块 Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了 ...
- 【BZOJ 3295】动态逆序对 - 分块+树状数组
题目描述 给定一个1~n的序列,然后m次删除元素,每次删除之前询问逆序对的个数. 分析:分块+树状数组 (PS:本题的CDQ分治解法见下一篇) 首先将序列分成T块,每一块开一个树状数组,并且先把最初的 ...
- 【bzoj3744】Gty的妹子序列 分块+树状数组+主席树
题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成 ...
- 【分块+树状数组】codechef November Challenge 2014 .Chef and Churu
https://www.codechef.com/problems/FNCS [题意] [思路] 把n个函数分成√n块,预处理出每块中各个点(n个)被块中函数(√n个)覆盖的次数 查询时求前缀和,对于 ...
- bzoj2141: 排队(分块+树状数组)
块套树为什么会这么快.. 先跑出原序列逆序对. 显然交换两个位置$l,r$,对$[1,l),(r,n]$里的数没有影响,所以只需要考虑$[l,r]$内的数. 设$(l,r)$内的数$a_i$,则按以下 ...
- BZOJ 2141 排队(分块+树状数组)
题意 第一行为一个正整数n,表示小朋友的数量:第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高:第三行为一个正整数m,表示交换操作的次数:以下m行每行包含两个正整数 ...
- Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2886 Solved: 924[Submit][Stat ...
- 【XSY2111】Chef and Churus 分块 树状数组
题目描述 有一个长度为\(n\)的数组\(A\)和\(n\)个区间\([l_i,r_i]\),有\(q\)次操作: \(1~x~y\):把\(a_x\)改成\(y\) \(2~x~y\):求第\(l\ ...
随机推荐
- linux下进程的最大线程数、进程最大数、进程打开的文件数
linux下进程的最大线程数.进程最大数.进程打开的文件数 ===========最大线程数============== linux 系统中单个进程的最大线程数有其最大的限制 PTHREAD_TH ...
- go web cookie和session
cookie是存储在浏览器端,session是服务器端 cookie是有时间限制的,分会话cookie和持久cookie,如果不设置时间,那周期就是创建到浏览器关闭为止.这种是会话cookie,一般保 ...
- CentOS(Linux)安装KETTLE教程 并配置执行定时任务
1,首先是安装jdk,并设置环境变量 采用yum安装可不设置环境变量 2,下载kettle https://sourceforge.net/projects/pentaho/files/Data%20 ...
- R语言学习笔记(二): 类与泛型函数
类 大多数R对象都是基于S3类(来源于第三代S语言),例如直方图函数hist()输出是一个包含多个组件的列表,它还有一个属性(attribute),用来指定列表的类,即histogram类. 泛型函数 ...
- linux io 学习笔记(03)---共享内存,信号灯,消息队列
system V IPC 1)消息队列 2)共享内存 3)信号灯(信号量集) 1.消息队列. ipcs -q 查看系统中使用消息队列的情况 ipcrm -q +msqid 删除消息队列 消息队列工作原 ...
- FIFO的使用场景
(1) 数据的缓冲.如模型图所示,如果数据的写入速率高,但间隔大,且会有突发;读出速率小,但相对均匀.则通过设置相应深度的FIFO,可以起到数据暂存的功能,且能够使后续处理流程平滑,避免前级突发时,后 ...
- mock.js中新增测试接口无效,返回404
项目是使用的npm+vue+mock模拟数据 我碰到的是在mock配置文件中新增接口,但是接口在测试时无效,返回404.但是在前端代码中把新接口换成配置文件中之前就有的,然后测试就正常了. 所以按问题 ...
- mysql 函数以及操作总结
1. 拼接 concat(参数1,参数2,.. ,参数) 实现将多个字符串拼接到一起 要批量修改一个字段值 字段值又是复杂的sql 计算得来 通过查询字段值 和 修改的条件fundId(这是 ...
- oracle 开启归档日志模式
摘自:https://www.jianshu.com/p/f8c0e9309ce2 在默认情况下,oracle数据库是在非归日志档模式中创建的,在非归档日志模式中,进行日志切换时会直接重写redo l ...
- ubuntu 14.04安装nginx+php
转自:http://www.cnblogs.com/helinfeng/p/4219051.html 基于最新的Ubuntu 14.04(2014年9月)搭建nginx.php.mysql环境,以下全 ...