[BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树)

题面

给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数

分析

每次都对整个序列求逆序对显然不行,考虑每次删除对逆序对个数的影响

假如删除的数为x,x在序列中的位置为pos[x],那么包含x的逆序对个数为位置在[1,pos[x]-1]中大于x的数+位置在[pos[x]+1,n]中小于x的数,每次删除只要减去这些就可以了

那么这个问题其实就转化成查询位置在[L,R]内,且值域在[l,r]内的数的个数。本质上和带修区间第k大BZOJ 1901 Dynamic Rankings是一样的,外层用树状数组维护位置,内层不用可持久化,直接用权值线段树即可

那么我们像树状数组那样维护n棵权值线段树,不同的是每棵权值线段树里保存的是,a[i-lowbit(i)+1]~a[i]有多少个值落在区间[l,r]内

对于查询[ql,qr]中有多少个值时的做差

我们要像树状数组求和那样,把root[i],root[i-lowbit(i)],....共O(logn)棵权值线段树的值加起来,才能得到a[1]a[i]有多少个数落在1qr里面,1~(ql-1)同理,维护两个临时数组x,y存储这O(logn)棵权值线段树的根即可

对于单点修改,我们像树状数组修改那样,往O(logn)棵权值线段树中插入即可

时间复杂度\(O(m \log ^2 n)\),常数略大

注意答案一定要开long long!!!!

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100000
#define maxm 100000
#define maxnlogn 50000000
#define maxlogn 20
using namespace std;
inline void qread(int &x) {
x=0;
int sign=1;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') sign=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
x=x*sign;
}
inline void qprint(long long x) {
if(x<0) {
putchar('-');
qprint(-x);
} else if(x==0) {
putchar('0');
return;
} else {
if(x>=10) qprint(x/10);
putchar('0'+x%10);
}
} int n,m;
int a[maxn+5];
struct segment_tree_val{
#define lson(x) (tree[x].ls)
#define rson(x) (tree[x].rs)
struct node{
int ls;
int rs;
int v;
}tree[maxnlogn+5];
int ptr;
void push_up(int x){
tree[x].v=tree[lson(x)].v+tree[rson(x)].v;
}
void update(int &x,int upos,int uval,int l,int r){
if(!x) x=++ptr;
if(l==r){
tree[x].v+=uval;
return;
}
int mid=(l+r)>>1;
if(upos<=mid) update(tree[x].ls,upos,uval,l,mid);
else update(tree[x].rs,upos,uval,mid+1,r);
push_up(x);
}
int totx,toty;
int x[maxn+5],y[maxn+5];
int query_less(int k,int l,int r){//查询<k的数的个数
int cnt=0;
while(l!=r){
int mid=(l+r)>>1;
if(k<=mid){
for(int i=1;i<=totx;i++) x[i]=lson(x[i]);
for(int i=1;i<=toty;i++) y[i]=lson(y[i]);
r=mid;
}else{
for(int i=1;i<=totx;i++) cnt-=tree[lson(x[i])].v;
for(int i=1;i<=toty;i++) cnt+=tree[lson(y[i])].v;
for(int i=1;i<=totx;i++) x[i]=rson(x[i]);
for(int i=1;i<=toty;i++) y[i]=rson(y[i]);
l=mid+1;
}
}
return cnt;
}
int query_more(int k,int l,int r){//查询>k的数的个数
int cnt=0;
while(l!=r){
int mid=(l+r)>>1;
if(k<=mid){
for(int i=1;i<=totx;i++) cnt-=tree[rson(x[i])].v;
for(int i=1;i<=toty;i++) cnt+=tree[rson(y[i])].v;
for(int i=1;i<=totx;i++) x[i]=lson(x[i]);
for(int i=1;i<=toty;i++) y[i]=lson(y[i]);
r=mid;
}else{
for(int i=1;i<=totx;i++) x[i]=rson(x[i]);
for(int i=1;i<=toty;i++) y[i]=rson(y[i]);
l=mid+1;
}
}
return cnt;
}
}T1; struct fenwick_tree{
inline int lowbit(int x){
return x&(-x);
}
int root[maxn+5];
void update(int t2pos,int t1pos,int val){
for(int i=t2pos;i<=n;i+=lowbit(i)){
T1.update(root[i],t1pos,val,1,n);
}
}
int query_less(int lpos,int rpos,int val){
T1.totx=T1.toty=0;
for(int i=lpos-1;i;i-=lowbit(i)) T1.x[++T1.totx]=root[i];
for(int i=rpos;i;i-=lowbit(i)) T1.y[++T1.toty]=root[i];
return T1.query_less(val,1,n);
}
int query_more(int lpos,int rpos,int val){
T1.totx=T1.toty=0;
for(int i=lpos-1;i;i-=lowbit(i)) T1.x[++T1.totx]=root[i];
for(int i=rpos;i;i-=lowbit(i)) T1.y[++T1.toty]=root[i];
return T1.query_more(val,1,n);
}
}T2; int pos[maxn+5];
long long ans=0;
int main(){
// freopen("4.in","r",stdin);
// freopen("4.out","w",stdout);
// freopen("1.txt","r",stdin);
int x;
qread(n);
qread(m);
for(int i=1;i<=n;i++){
qread(a[i]);
pos[a[i]]=i;
ans+=T2.query_more(1,i-1,a[i]);
T2.update(i,a[i],1);
}
qprint(ans);
putchar('\n');
for(int i=1;i<m;i++){
qread(x);
ans-=T2.query_more(1,pos[x]-1,x);
ans-=T2.query_less(pos[x]+1,n,x);
qprint(ans);
putchar('\n');
T2.update(pos[x],x,-1);
}
}
/*
5 4
1 5 3 4 2
5
1
4
2 */

[BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)的更多相关文章

  1. [Luogu P3157][CQOI2011]动态逆序对 (树套树)

    题面 传送门:[CQOI2011]动态逆序对 Solution 一开始我看到pty巨神写这套题的时候,第一眼还以为是个SB题:这不直接开倒车线段树统计就完成了吗? 然后冷静思考了一分钟,猛然发现单纯的 ...

  2. luogu P3157 [CQOI2011]动态逆序对(CDQ分治)

    题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序 ...

  3. Luogu P3157 [CQOI2011]动态逆序对

    题目链接 \(Click\) \(Here\) 这个题有点卡常数..我的常数比较大所以是吸着氧气跑过去的... 题意:计算对于序列中每个位置\(p\),\([1,p-1]\)区间内比它大的数的个数,和 ...

  4. LUOGU P3157 [CQOI2011]动态逆序对(CDQ 分治)

    传送门 解题思路 cdq分治,将位置看做一维,修改时间看做一维,权值看做一维,然后就转化成了三维偏序,用排序+cdq+树状数组.注意算删除贡献时要做两次cdq,分别算对前面和后面的贡献. #inclu ...

  5. BZOJ - 2141 排队 (动态逆序对,区间线段树套权值线段树)

    题目链接 交换两个数的位置,只有位于两个数之间的部分会受到影响,因此只需要考虑两个数之间有多少数对a[l]和a[r]产生的贡献发生了变化即可. 感觉像是个带修改的二维偏序问题.(修改点$(x,y)$的 ...

  6. bzoj 3295 (洛谷3157、3193) [Cqoi2011]动态逆序对——树套树 / CDQ分治

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3295 题目--洛谷3157:https://www.luogu.org/problemnew ...

  7. [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)

    [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...

  8. BZOJ 3295: [Cqoi2011]动态逆序对

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3865  Solved: 1298[Submit][Sta ...

  9. Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2886  Solved: 924[Submit][Stat ...

随机推荐

  1. MySql的导入导出

    可以参看之前的博客:https://www.cnblogs.com/shijinglu2018/p/8672699.html 可以参看视频:https://i.cnblogs.com/EditPost ...

  2. css3 中的2D转换

    一.CSS3转换 通过转换实现对对元素进行旋转.缩放.移动.拉伸的效果:这种原来必须要通过JS或者图片处理才可以实现的效果,现在都可以通过CSS3来完成. 2D转换采用transform属性来实现效果 ...

  3. Bugku 杂项 猜

    猜 说flag是一个人名字的全拼,直接搜图片

  4. JS&ASPDotNet_大文件上传问题

    HTML部分 <%@PageLanguage="C#"AutoEventWireup="true"CodeBehind="index.aspx. ...

  5. 软件安装——internal error2503/2502

    安装新的软件后先报internal error 2503,随后报internal error 2502.就是不让我装新的软件,提示说发生严重错误,然后安装失败. Solution for intern ...

  6. DOS命令里面的EQ、NE、GT、LT、GE、LE分别是什么意思

    EQ 就是 EQUAL等于NQ 就是 NOT EQUAL不等于 GT 就是 GREATER THAN大于 LT 就是 LESS THAN小于 GE 就是 GREATER THAN OR EQUAL 大 ...

  7. [洛谷3934]P3934 Nephren Ruq Insania题解

    先放个奈芙莲 解法 看到这种题目就知道是欧拉降幂,然后根据某玄学证明,递归欧拉降幂从l到r不会超过\(\Theta(log_n)\),所以直接递归解决,然后区间修改直接树状数组维护一下 然后就A了 代 ...

  8. IOC和AOP使用扩展之AOP详解实现类

    摘要:   “Depend on yourself” is what nature says to every man.  Parents can help you. Teachers can hel ...

  9. android读取xml

    /*** 从config.xml中获取版本信息以及应用id* * @param urlPath* @return* @throws Exception*/public List getUpdateIn ...

  10. Linux超全实用指令大全

    参考 Linux超全实用指令大全