26天以前做过的一道题,之前的做法是分治预处理,树套树在线修改,复杂度为O(nlogn+m*logn*logn),代码量较大。

本来想学习一下cdq分治的,看到论文上的凸包、斜率就暂时放一边了,只知道和一般的分治的不同是左子问题可以用来解决右边的子问题。

今天下午YY了一个离线的分治做法,也不知道叫不叫cdq。

Analysis:

对于每一个数字,构成逆序对除了val大小还和被删除的时间del有关,这实际上是一个三维偏序的问题。

一个元素是一个三元组e(pos,val,del),e1和e2对答案有贡献当且仅当e1.pos < e1.pos && e1.val > e2.val && e1.del > e2.del。

第一维pos已经给好了,第二个维度就用归并,而第三个维度就用树状数组(BIT)。用BIT的想法来源于,BIT插入的顺序对应着之前都

已经满足的序,在这里就是已经满足e1.pos < e1.pos && e1.val > e2.val ,然后用del查询作为下标就可以查询到满足第三个条件e1.del > e2.del的元素个数。

Note:

思想如此,实现上有还值得注意的地方,一是BIT插入的值域范围不能太大,所以我记录了两个关于时间的信息tKth[],tRank[],

tKth[i]表示当前区间第i大的del,tRank[del]表示del在当前区间的名次,(名次从1开始,0表示没有删去),可以很方便地用归并去维护。

二是BIT只能查询小的,需要转化。总对数是容易得到的,用总对数去减就好了。

BIT需要事先知道值域范围,这题只有删除,如果带有修改则应该改成平衡树。

复杂度

依然是O(nlogn+m*logn*logn),但常数很小,代码量也比较小。

#include<bits/stdc++.h>
using namespace std; typedef long long ll; const int maxn = 2e5+, maxm = 1e5+;
ll ans;
int iv_pir[maxn], a[maxn], tRank[maxn], tKth[maxn];
int del[maxn], temp[maxn];
int C[][maxn];
int qry[maxm]; #define lb(x) (x&-x)
void add(int C[],int x,int d,int range)
{
//if(x<1) return;
while(x <= range){
C[x] += d; x += lb(x);
}
} int sum(int C[],int x)
{
int re = ;
while(x>){
re += C[x]; x -= lb(x);
}
return re;
} void divide(int l,int r)
{
if(l == r) {
if(del[a[l]]) {
tKth[l] = del[a[l]];
}
return;
}
int mid = (l+r)>>;
divide(l, mid);
divide(mid+, r);
//conquer int p = l, q = mid+, k = ;
while(p <= mid && !tKth[p]) { temp[k++] = ; p++; }
while(q <= r && !tKth[q]) { temp[k++] = ; q++; }
int base = l+k-;
while(p<=mid || q<=r){
if(p>mid || (q<=r && tKth[p] > tKth[q])) {
temp[k++] = tKth[q++];
}else {
temp[k++] = tKth[p++];
}
}
memcpy(tKth+l,temp,sizeof(int)*k);
for(int i = base+; i <= r; i++){
tRank[tKth[i]] = i-base;
}
int sz = r-base;
memset(C[]+,,sizeof(int)*(sz));
memset(C[]+,,sizeof(int)*(sz));
for(int i = l; i <= mid; i++) {
if(del[a[i]])
add(C[],tRank[del[a[i]]],,sz);
} p = l, q = mid+, k = ;
while(p<=mid || q<=r){
if(p>mid || (q<=r && a[p] > a[q])) {
ans += mid-p+;
if(del[a[q]]){
iv_pir[a[q]] += mid-p+ - sum(C[], tRank[del[a[q]]]);
add(C[], tRank[del[a[q]]], , sz);
}
temp[k++] = a[q++];
}else {
if(del[a[p]]){
iv_pir[a[p]] += q-mid- - sum(C[], tRank[del[a[p]]]);
add(C[], tRank[del[a[p]]], -, sz);
}
temp[k++] = a[p++];
}
}
memcpy(a+l, temp, sizeof(int)*k);
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
int n, m; ;
while(~scanf("%d%d", &n, &m)){
for(int i = ; i < n; i++) scanf("%d", a+i);
memset(del+,,sizeof(int)*n);
for(int i = ; i <= m; i++) {
scanf("%d", qry+i);
del[qry[i]] = i;
iv_pir[qry[i]] = ;
}
ans = ;
divide(,n-);
for(int i = ; i <= m; i++){
printf("%lld\n", ans);
ans -= iv_pir[qry[i]];
}
}
return ;
}

UVA 11990 ``Dynamic'' Inversion (序列分治)的更多相关文章

  1. UVA 11990 `Dynamic'' Inversion CDQ分治, 归并排序, 树状数组, 尺取法, 三偏序统计 难度: 2

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  2. UVA 11990 ``Dynamic'' Inversion 动态逆序对

    ``Dynamic'' Inversion Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://uva.onlinejudge.org/index ...

  3. UVA 11990 ``Dynamic'' Inversion (线段树套BIT,分治)

    题目要求可转化为查询一个区间内有多少数比val大(或者小). 区间用线段树分解(logN),每个区间维护一rank树. rank可用BIT查询,往BIT里面插值,为了保证不同区间的BIT互不影响要先离 ...

  4. UVA 11990 ”Dynamic“ Inversion(线段树+树状数组)

    [题目链接] UVA11990 [题目大意] 给出一个数列,每次删去一个数,求一个数删去之前整个数列的逆序对数. [题解] 一开始可以用树状数组统计出现的逆序对数量 对于每个删去的数,我们可以用线段树 ...

  5. [CF888E] Maximum Subsequence 序列分治

    早期作品,不喜轻喷. LG传送门 序列分治板子题. 切这道题用了好长时间,所以想发篇题解作为纪念 . 首先,我们认真观察题目数据(面向数据做题是个好习惯),发现题目的\(n\)竟然只有\(35\),我 ...

  6. 算法复习——序列分治(ssoj光荣的梦想)

    题目: 题目描述 Prince对他在这片大陆上维护的秩序感到满意,于是决定启程离开艾泽拉斯.在他动身之前,Prince决定赋予King_Bette最强大的能量以守护世界.保卫这里的平衡与和谐.在那个时 ...

  7. UVA - 1625 Color Length[序列DP 代价计算技巧]

    UVA - 1625 Color Length   白书 很明显f[i][j]表示第一个取到i第二个取到j的代价 问题在于代价的计算,并不知道每种颜色的开始和结束   和模拟赛那道环形DP很想,计算这 ...

  8. Uva 3767 Dynamic len(set(a[L:R])) 树套树

    Dynamic len(set(a[L:R])) Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://uva.onlinejudge.org/in ...

  9. UVA - 1625 Color Length[序列DP 提前计算代价]

    UVA - 1625 Color Length   白书 很明显f[i][j]表示第一个取到i第二个取到j的代价 问题在于代价的计算,并不知道每种颜色的开始和结束   和模拟赛那道环形DP很想,计算这 ...

随机推荐

  1. cinder介绍及使用lvm本地存储

    1.cinder简介 Cinder提供持久的块存储,目前仅供给虚拟机挂载使用.它并没有实现对块设备的管理和实际服务,而是为后端不同的存储结构提供了统一的接口,不同的块设备服务厂商在 Cinder 中实 ...

  2. weex前端式写法解决方案---eros

    前言 如果想用前端的方式写一个app怎么办呢? 如果你用的是 React,那么它已经有了一个比较完善的体系跟社区.如果你用的是Vue又不想花费太多时间去重新学习React,那么目前比较靠谱的方案就是w ...

  3. Mysql-4-数据库的基本操作

    1.创建数据库 create database database_name; 例:create database aa; show create database aa;(查看database aa) ...

  4. 我的省选 Day -14

    Day -14 07:43:27 到机房了,不知道早上要做什么题,要不去选一题NOI原题来试试水好了 (因为NOI的原题质量比较有保证吧..) 09:11:22 正在做NOI2016的网格 开始写自己 ...

  5. Git Remote (转)

    基本使用 git是一个分布式代码管理工具,所以可以支持多个仓库,在git里,服务器上的仓库在本地称之为remote. 直接clone一个仓库: $: git clone git@search.ued. ...

  6. 11gR2 ASM RAC + ASM RAC dataguard配置

    1.环境说明 --primary端配置 Primary RAC Node1 Node2 Public IP 192.168.56.120 192.168.56.122 Private IP 10.0. ...

  7. 点击对应的a标签返回相应的第几个

    面试中遇到的问题,前两天一直没有解决,今天想想还是得要想办法才行,其实仔细想的话很简单,惭愧啊,面试的时候没有做出来! 题目是这样的,如果一个body中有5个a标签,当我们点击对应的a标签时,aler ...

  8. 7、python数据类型之集合set

    数据类型之集合setset 不允许重复的无序集合,不能通过下标取值,因为无序1.创建   创建空集合   s ={} 默认类型为字典,所以不是空集合,空集合如下   s = set()   s = { ...

  9. PHPExcel探索之旅---阶段四 导入文件

    步骤就是:实例化excel读取对象=> 加载excel文件 => 读取excel文件(全部读取.逐行读取) <?php header("Content Type :text ...

  10. List<Object> 使用Linq

    List<Asset> bdList = allAsset.Where(m => m.Owner.Depts == view.DeptName).ToList(); var quer ...