【BZOJ3295】【块状链表+树状数组】动态逆序对
Description
Input
Output
Sample Input
1
5
3
4
2
5
1
4
2
Sample Output
2
2
1
样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
HINT
N<=100000 M<=50000
【分析】
这种水题还弄了两节课...真是没法治了。
用很多种方法,最好理解的就是块状链表套树状数组,每个块状链表里面套一个二维的树状数组,再加上离散化。
将m序列中的每一个数字对应一个坐标(在n中坐标,n-数字大小)然后就可以做了。
我还开了3个一维树状数组,卡着时间过的。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <assert.h>
#include <map> const int N = + ;
const int SIZE = ;//块状链表的根号50000
const int M = + ;
using namespace std;
typedef long long ll;
int lowbit(int x) {return x & -x;}
struct BLOCK_LIST{
int C[SIZE][SIZE];
int t[][SIZE];//关于a的离散化序列和b的离散化序列
void init(){
memset(C, , sizeof(C));
memset(t, , sizeof(t));
}
int sum(int x, int y){
int cnt = , f = y;
//int flag = x;
while (x > ){
while (y > ){
cnt += C[x][y];
y -= lowbit(y);
}
x -= lowbit(x);
y = f;
}
return cnt;
}
void add(int x, int y){
int f = y;
while (x < SIZE){
while (y < SIZE){
C[x][y]++;
y += lowbit(y);
}
x += lowbit(x);
y = f;
}
return;
}
//二分搜索,查找x在k内相当的值
int search(int k, int x){
int l = , r = , Ans;
while (l <= r){
int mid = (l + r) >> ;
if (t[k][mid] <= x) Ans = mid, l = mid + ;
else r = mid - ;
}
return Ans;
}
}list[SIZE];
struct DATA{
int t[];//影响m的树状数组的两个值,注意都要进行离散化
int x;//值
}rem[M];
struct LSH{
int num, order;
bool operator < (LSH b)const{
return num < b.num;//专门用来离散化
}
}A[M];
int data[N], c[][N], n, m;
int num[N];//num[N]代表i有i存在的逆序对的个数
ll tot;//记录逆序对的个数 ll sum(int k, int x){
ll cnt = ;
while (x > ){
cnt += c[k][x];
x -= lowbit(x);
}
return cnt;//记得要用ll
}
void add(int k, int x){
while (x <= n){
c[k][x]++;
x += lowbit(x);
}
return;
}
void init(){
tot = ;
memset(num, , sizeof(num));
memset(c, , sizeof(c));
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++){
int x;
scanf("%d", &x);
data[x] = i;
int tmp = sum(, x);
num[x] += (i - - tmp);//先求出在i之前的比i大的数
num[x] += (x - tmp - );//后面比i小的数
tot += (i - - tmp);
add(, x);
}
//printf("%d\n", tot);
//for (int i = 1; i <= n; i++) printf("%d\n", num[i]);
}
//离散化
void prepare(){
//a,b中两个值分别为位置和大小
for (int i = ; i <= m; i++){
int tmp;
scanf("%d", &tmp);
rem[i].t[] = data[tmp];
rem[i].t[] = n - tmp + ;
rem[i].x = tmp;
}
//for (int i = 1; i <= m; i++) printf("%d %d %d\n", rem[i].t[0], rem[i].t[1], rem[i].x);
}
void get(int k, int l, int r, int x){
int cnt = r - l + , pos = ;
for (int i = l; i <= r; i++){
A[pos].order = i;
A[pos].num = rem[i].t[k];
pos++;
}
sort(A + , A + cnt + );
for (int i = ;i <= cnt; i++) list[x].t[k][i] = A[i].num;
for (int i = ;i <= cnt; i++) rem[A[i].order].t[k] = i;
}
void work(){
for (int i = ; i < SIZE; i++) list[i].init();
int cnt = ;//cnt是用来记录块的数量
for (int pos = ; pos <= m; pos++){ int l = pos;
l = min(m , + pos - );
//从[l,m]这一段放在list[cnt]里面
get(, pos, l, cnt);
get(, pos, l, cnt);
for (int i = pos; i <= l; i++){
printf("%lld\n", tot);
int tmp = list[cnt].sum(rem[i].t[], rem[i].t[]);
for (int j = ; j < cnt; j++) tmp += list[j].sum(list[j].search(, list[cnt].t[][rem[i].t[]]), list[j].search(, list[cnt].t[][rem[i].t[]])); tot -= (num[rem[i].x] - (tmp + (sum(, rem[i].x) - (sum(, list[cnt].t[][rem[i].t[]]) - tmp))));
list[cnt].add(rem[i].t[], rem[i].t[]);
add(, list[cnt].t[][rem[i].t[]]);
add(, rem[i].x);
}
cnt++;
pos = l;
}
} int main(){
#ifdef LOCAL
freopen("data.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
init();
prepare();
if (m == ) return ;
else work();
return ;
}
【BZOJ3295】【块状链表+树状数组】动态逆序对的更多相关文章
- POJ2299Ultra-QuickSort(归并排序 + 树状数组求逆序对)
树状数组求逆序对 转载http://www.cnblogs.com/shenshuyang/archive/2012/07/14/2591859.html 转载: 树状数组,具体的说是 离散化+树 ...
- poj3067 Japan 树状数组求逆序对
题目链接:http://poj.org/problem?id=3067 题目就是让我们求连线后交点的个数 很容易想到将左端点从小到大排序,如果左端点相同则右端点从小到大排序 那么答案即为逆序对的个数 ...
- SGU180(树状数组,逆序对,离散)
Inversions time limit per test: 0.25 sec. memory limit per test: 4096 KB input: standard output: sta ...
- [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)
[NOIP2013提高&洛谷P1966]火柴排队 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...
- [NOI导刊2010提高&洛谷P1774]最接近神的人 题解(树状数组求逆序对)
[NOI导刊2010提高&洛谷P1774]最接近神的人 Description 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某 ...
- 【bzoj2789】[Poi2012]Letters 树状数组求逆序对
题目描述 给出两个长度相同且由大写英文字母组成的字符串A.B,保证A和B中每种字母出现的次数相同. 现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B. 输入 第一行一个正整数n ...
- poj3067Japan——树状数组查找逆序对
题目:http://poj.org/problem?id=3067 利用树状数组查找逆序对. 代码如下: #include<iostream> #include<cstdio> ...
- “浪潮杯”第九届山东省ACM大学生程序设计竞赛(重现赛)E.sequence(树状数组求逆序对(划掉))
传送门 E.sequence •题意 定义序列 p 中的 "good",只要 i 之前存在 pj < pi,那么,pi就是 "good": 求删除一个数, ...
- 2021.12.10 P5041 [HAOI2009]求回文串(树状数组求逆序对)
2021.12.10 P5041 [HAOI2009]求回文串(树状数组求逆序对) https://www.luogu.com.cn/problem/P5041 题意: 给一个字符串 \(S\) ,每 ...
- NOIP 2013 洛谷P1966 火柴排队 (树状数组求逆序对)
对于a[],b[]两个数组,我们应选取其中一个为基准,再运用树状数组求逆序对的方法就行了. 大佬博客:https://www.cnblogs.com/luckyblock/p/11482130.htm ...
随机推荐
- 【转】ButterKnife基本使用--不错
原文网址:http://www.cnblogs.com/mengdd/archive/2015/06/23/4595973.html Butter Knife处理字段和方法绑定. 配置: 用gradl ...
- VS2010编译libjpeg
环境:win7旗舰版 x64 VS2010 下载源代码下载地址:http://www.ijg.org/,选择windows format file 解压源代码,修改源代码中jconfig.vc为jco ...
- 装饰模式,制作一个蛋糕java
import java.text.DecimalFormat; //抽象组件组件 interface mkcake { public void cake(); } class Cake impleme ...
- Bzoj 1703: [Usaco2007 Mar]Ranking the Cows 奶牛排名 传递闭包,bitset
1703: [Usaco2007 Mar]Ranking the Cows 奶牛排名 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 323 Solved ...
- linux-kernel/CodingStyle
https://www.kernel.org/doc/Documentation/zh_CN/CodingStyle Chinese translated version of Documentati ...
- JAVA 线程状态以及synchronized,wait,sleep,yield,notify,notifyAll
java线程存在以下几种状态: 1: 创建状态(New):线程被new出来,还未调用start 2: 就绪状态(Runnable):又称为可执行状态,调用线程的start方法后,线程处于就绪状态,,线 ...
- config 数据库字符串的读取、修改 分类: WebForm 2014-12-16 10:24 203人阅读 评论(0) 收藏
config数据库字符串: <connectionStrings> <add name="MyWebDataString" connectionString= ...
- 娓娓道来c指针 (3)指针和数组
(3)指针和数组 在c中指针和数组似乎有着千丝万缕的关系.事实上它们不是一回事:指针是指针,数组是数组.两者不同样. 说它们有关系,只是是由于常见这种代码: int main() { int arra ...
- Phonegap(Cordova)3.4 + Android 环境搭建
PhoneGap是一个用基于HTML.CSS和JavaScript的,创建移动跨平台移动应用程序的高速开发平台. 它使开发人员可以利用iPhone,Android,WP7等多 ...
- Qt 学习之路:坐标系统
在经历过实际操作,以及前面一节中我们见到的那个translate()函数之后,我们可以详细了解下 Qt 的坐标系统了.泛泛而谈坐标系统,有时候会觉得枯燥无味,难以理解,好在现在我们已经有了基础. 坐标 ...