UVA 11990 ``Dynamic'' Inversion (序列分治)
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 (序列分治)的更多相关文章
- UVA 11990 `Dynamic'' Inversion CDQ分治, 归并排序, 树状数组, 尺取法, 三偏序统计 难度: 2
题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...
- UVA 11990 ``Dynamic'' Inversion 动态逆序对
``Dynamic'' Inversion Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://uva.onlinejudge.org/index ...
- UVA 11990 ``Dynamic'' Inversion (线段树套BIT,分治)
题目要求可转化为查询一个区间内有多少数比val大(或者小). 区间用线段树分解(logN),每个区间维护一rank树. rank可用BIT查询,往BIT里面插值,为了保证不同区间的BIT互不影响要先离 ...
- UVA 11990 ”Dynamic“ Inversion(线段树+树状数组)
[题目链接] UVA11990 [题目大意] 给出一个数列,每次删去一个数,求一个数删去之前整个数列的逆序对数. [题解] 一开始可以用树状数组统计出现的逆序对数量 对于每个删去的数,我们可以用线段树 ...
- [CF888E] Maximum Subsequence 序列分治
早期作品,不喜轻喷. LG传送门 序列分治板子题. 切这道题用了好长时间,所以想发篇题解作为纪念 . 首先,我们认真观察题目数据(面向数据做题是个好习惯),发现题目的\(n\)竟然只有\(35\),我 ...
- 算法复习——序列分治(ssoj光荣的梦想)
题目: 题目描述 Prince对他在这片大陆上维护的秩序感到满意,于是决定启程离开艾泽拉斯.在他动身之前,Prince决定赋予King_Bette最强大的能量以守护世界.保卫这里的平衡与和谐.在那个时 ...
- UVA - 1625 Color Length[序列DP 代价计算技巧]
UVA - 1625 Color Length 白书 很明显f[i][j]表示第一个取到i第二个取到j的代价 问题在于代价的计算,并不知道每种颜色的开始和结束 和模拟赛那道环形DP很想,计算这 ...
- 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 ...
- UVA - 1625 Color Length[序列DP 提前计算代价]
UVA - 1625 Color Length 白书 很明显f[i][j]表示第一个取到i第二个取到j的代价 问题在于代价的计算,并不知道每种颜色的开始和结束 和模拟赛那道环形DP很想,计算这 ...
随机推荐
- CentOS7 LVM磁盘扩容
1:创建磁盘分区(注意红色命令部分) [root@hongyin-test- ~]# fdisk /dev/sda Welcome to fdisk (util-linux ). Changes wi ...
- 2017-10-12 NOIP模拟赛
斐波那契 /* 相同颜色的节点与父亲节点的差相等,且是一个小于它的最大斐波那契数 所以降两个点同时减去小与它的最大斐波那契数,直到两点相等 */ #include<cstdio> ; ...
- c语言指针,数组
指针:说简单点就是一个地址.例如int *p,p是个变量,里面放的是地址0x0000,同理,每一个指针,不管什么类型,都是地址,也就是空间都是4个字节(32位机). 以此类推,指针也有指向它的指针in ...
- Shell面试,笔试整理
1.经典Shell脚本面试问题:https://blog.csdn.net/hyszyl/article/details/60970307
- 阿里maven镜像配置
setting.xml<mirrors> <mirror> <id>alimaven</id> <name>aliyun maven< ...
- CSS之flex兼容
我觉得写的很好的文章,但是我又没有时间去整理的. https://blog.csdn.net/u010130282/article/details/52627661 百分比 是在宽度自适应的时候要用 ...
- Luogu P1768 天路 0/1分数规划+dfs spfa
“那是一条神奇的天路诶~~把第一个神犇送上天堂” 怕不是某大佬早就A了这题,然鹅我又调了很久很久... 好吧就是0/1分数规划,但是跑的dfs的spfa(好像题解说bfs过不了????不知) 发现把s ...
- 73th LeetCode Weekly Contest Domino and Tromino Tiling
We have two types of tiles: a 2x1 domino shape, and an "L" tromino shape. These shapes may ...
- python_魔法方法(四):属性访问
通常可以通过点(.)操作符的形式去访问对象的属性,也可以通过BIF适当地去访问属性,看个例子吧 >>> class A(): def __init__(self): self.x = ...
- Raymond Mill In Lisp
Raymond Mill is suitable for producing minerals powder, which is widely used in the metallurgy, buil ...