[BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)
[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]动态逆序对(树状数组套权值线段树)的更多相关文章
- [Luogu P3157][CQOI2011]动态逆序对 (树套树)
题面 传送门:[CQOI2011]动态逆序对 Solution 一开始我看到pty巨神写这套题的时候,第一眼还以为是个SB题:这不直接开倒车线段树统计就完成了吗? 然后冷静思考了一分钟,猛然发现单纯的 ...
- luogu P3157 [CQOI2011]动态逆序对(CDQ分治)
题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序 ...
- Luogu P3157 [CQOI2011]动态逆序对
题目链接 \(Click\) \(Here\) 这个题有点卡常数..我的常数比较大所以是吸着氧气跑过去的... 题意:计算对于序列中每个位置\(p\),\([1,p-1]\)区间内比它大的数的个数,和 ...
- LUOGU P3157 [CQOI2011]动态逆序对(CDQ 分治)
传送门 解题思路 cdq分治,将位置看做一维,修改时间看做一维,权值看做一维,然后就转化成了三维偏序,用排序+cdq+树状数组.注意算删除贡献时要做两次cdq,分别算对前面和后面的贡献. #inclu ...
- BZOJ - 2141 排队 (动态逆序对,区间线段树套权值线段树)
题目链接 交换两个数的位置,只有位于两个数之间的部分会受到影响,因此只需要考虑两个数之间有多少数对a[l]和a[r]产生的贡献发生了变化即可. 感觉像是个带修改的二维偏序问题.(修改点$(x,y)$的 ...
- bzoj 3295 (洛谷3157、3193) [Cqoi2011]动态逆序对——树套树 / CDQ分治
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3295 题目--洛谷3157:https://www.luogu.org/problemnew ...
- [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)
[BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...
- BZOJ 3295: [Cqoi2011]动态逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3865 Solved: 1298[Submit][Sta ...
- Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2886 Solved: 924[Submit][Stat ...
随机推荐
- DOM-document 对象
Document 对象Document 对象代表整个HTML 文档,可用来访问页面中的所有元素.Document 对象是 Window 对象的一个部分,可通过 window.document 属性来访 ...
- postman(三):详解postman动态变量使用
参考: Variables Dynamic variables
- Azure IoT 技术研究系列1
物联网技术已经火了很多年了,业界各大厂商都有各自成熟的解决方案.我们公司主要搞新能源汽车充电,充电桩就是我们物联网技术的最大应用,车联网.物联网. 互联网三网合一.作为Azure重要的Partner和 ...
- Python---进阶---logging---装饰器打印日志2
### logging - logging.debug - logging.info - logging.warning - logging.error - logging.critical ---- ...
- SpringCloud学习系列-Eureka服务注册与发现(4)
actuator与注册微服务信息完善 1.主机名称:服务名称修改 当前问题 含有主机名称 修改修改microservicecloud-provider-dept-8001 的yml文件 修改内容 eu ...
- 【leetcode】1154. Day of the Year
题目如下: Given a string date representing a Gregorian calendar date formatted as YYYY-MM-DD, return the ...
- 关了浏览器再开,怎么session还在?
关了浏览器session当然仍然存在,因为session是储存在服务器端的,而服务器是不可能知道你有没有关掉浏览器. 服务器只是简单的保持session接受用户请求,只有当session一段时间没有被 ...
- phpstudy升级5.7
1:备份当前数据库数据. 最好是导成 SQL 文件 2:备份 PhpStudy 下的 MySQL 文件夹.以防升级失败.还可以使用旧版本的数据库 3:下载MySQL5.7.解压.然后放在 PhpStu ...
- BP神经网络设计
1.网络层数 大部分单个隐藏层即可 2.输入层神经元个数 输入变量的个数通常都是由问题的外部描述所确定的.例如,如果有4个外部变量作为网络的输入,那么网络就有4个输入.但是,这是不是意味着输入层的神经 ...
- volley简介
究竟什么是volley呢? 在以前的开发过程中,开发app的时候,使用的东西可能包括: 1.Httpclient,HttpURLConnection 2.AsyncTask,AsyncTaskLoa ...