Description

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

Input

输入第一行包含两个整数nm,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
 

Output

 
输出包含m行,依次为删除每个元素之前,逆序对的个数。

Sample Input

5 4
1
5
3
4
2
5
1
4
2

Sample Output

5
2
2
1

样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

HINT

N<=100000 M<=50000

思路

最近一直都在做一些树套树的题目呢=。=

求解逆序对有两种方法,树状数组和归并排序,前者一般来说优于后者。。而且好写太多了。

首先算出最初的答案ans,和一个数的左边比它大的数以及右边比它小的数的个数。

每次删除一个数之后,ans就减去左边比他大以及右边比他小的数的个数。

然而前面删除的时候有可能会对后面产生影响,于是我们维护在[l,r]范围内被删除的比I小的数的个数,那么就用树状数组套线段树组成。

外层树状数组记录权值,内层线段树记录位置,为了节省空间,线段树动态开点(要不然二维树状数组不就好了么。。)

一开始我没有记录最开始一个数的左边比它大的数以及右边比它小的数的个数,而是动态维护,导致线段树疯狂开点,怒E。。

一次查询最多只会涉及到Log2n个节点(树状数组Logn次查询*每次查询Logn个节点),于是总共的空间是mLog2n的,完全可以接受。

如果直接动态维护一个数的左边比它大的数以及右边比它小的数的个数的话空间复杂度是O(n2)的,Terrible。。

 #include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#include <vector>
#include <ctime>
#include <functional>
#define pritnf printf
#define scafn scanf
#define sacnf scanf
#define For(i,j,k) for(int i=(j);i<=(k);(i)++)
#define Clear(a) memset(a,0,sizeof(a))
using namespace std;
typedef unsigned int Uint;
const int INF=0x3fffffff;
///==============struct declaration==============
struct Seg_Node{
Seg_Node *lc,*rc;
int addv;
long long sum;
Seg_Node (){lc=rc=NULL;sum=;addv=;}
};
///==============var declaration=================
const int MAXN=;
int n,L,R,k,v,m;
long long ans=;
Seg_Node *BitTree[MAXN];
int A[MAXN],Index[MAXN],Prefix[MAXN];
int LeftGreater[MAXN],RightLess[MAXN],Bit[MAXN];
///==============function declaration============
void Add_Bit(int x);
void Add_Prefix(int x,int val);
int lowbit(int x){return x&-x;}
int Query_Prefix(int x);
long long Query_Bit(int x);
void Add_Seg(Seg_Node *&Node,int l,int r);
long long Query_Seg(Seg_Node *&Node,int l,int r,int add);
void update(Seg_Node *&Node,int l,int r);
inline void qread(int &x);
void Add_Bit(int *P,int x);
int Query_Bit(int *P,int x);
///==============main code=======================
int main()
{
//#define FILE__
#ifdef FILE__
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
qread(A[i]);
Index[A[i]]=i;k=i;v=;
Add_Prefix(i,);Add_Bit(Bit,A[i]);
LeftGreater[i]=i-Query_Bit(Bit,A[i]);
ans+=LeftGreater[i];
}
memset(Bit,,sizeof(Bit));
for(int i=n;i>=;i--){
Add_Bit(Bit,A[i]);
RightLess[i]=Query_Bit(Bit,A[i]-);
}
while (m--){
int num,pos;qread(num);pos=Index[num];
printf("%lld\n",ans);
int Left=,Right=;
ans-=LeftGreater[pos]+RightLess[pos];
L=,R=pos-;
if (L<=R)
Left=Query_Bit(n)-Query_Bit(num);
L=pos+,R=n;
if (L<=R)
Right=Query_Bit(num);
Add_Prefix(pos,-);k=pos;v=;
Add_Bit(num);
ans+=Left+Right;
}
return ;
}
///================fuction code====================
void Add_Bit(int x){
while (x<=n){
Add_Seg(BitTree[x],,n);
x+=lowbit(x);
}
}
void Add_Prefix(int x,int val){
while (x<=n){
Prefix[x]+=val;
x+=lowbit(x);
}
}
int Query_Prefix(int x){
int res=;
while (x>){
res+=Prefix[x];
x-=lowbit(x);
}
return res;
}
long long Query_Bit(int x){
long long res=;
while (x>){
res+=Query_Seg(BitTree[x],,n,);
x-=lowbit(x);
}
return res;
}
void Add_Seg(Seg_Node *&Node,int l,int r){
if (Node==NULL) Node=new(Seg_Node);
int m=(l+r)>>;
if (l==r){
Node->addv+=v;
Node->sum+=v;
return ;
}
if (m>=k) Add_Seg(Node->lc,l,m);
else Add_Seg(Node->rc,m+,r);
update(Node,l,r);
}
void update(Seg_Node *&Node,int l,int r){
Node->sum=;
if (Node->lc!=NULL) Node->sum+=Node->lc->sum;
if (Node->rc!=NULL) Node->sum+=Node->rc->sum;
Node->sum+=(r-l+)*Node->addv;
}
long long Query_Seg(Seg_Node *&Node,int l,int r,int add){
if (Node==NULL) return (r-l+)*add;
if (L<=l&&r<=R) return Node->sum+add*(r-l+);
int m=(l+r)>>;
long long Left=,Right=;
if (m>=L) Left=Query_Seg(Node->lc,l,m,add+Node->addv);
if (m<R) Right=Query_Seg(Node->rc,m+,r,add+Node->addv);
return Left+Right;
}
inline void qread(int &x){
char cha;
while(cha=getchar()) if(isdigit(cha)) break;
x=cha-'';
while(cha=getchar()){
if(!isdigit(cha)) break;
x=*x+cha-'';
}
}
void Add_Bit(int *P,int x){
while (x<=n){
P[x]++;
x+=lowbit(x);
}
}
int Query_Bit(int *P,int x){
int res=;
while (x>){
res+=P[x];
x-=lowbit(x);
}
return res;
}

BZOJ3295

【CQOI2011】动态逆序对 BZOJ3295的更多相关文章

  1. 【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治

    [BZOJ3295][Cqoi2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依 ...

  2. bzoj3295 [Cqoi2011]动态逆序对 cdq+树状数组

    [bzoj3295][Cqoi2011]动态逆序对 2014年6月17日4,7954 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数. ...

  3. [bzoj3295][Cqoi2011]动态逆序对_主席树

    动态逆序对 bzoj-3295 Cqoi-2011 题目大意:题目链接. 注释:略. 想法:直接建立主席树. 由于是一个一个删除,所以我们先拿建立好的root[n]的权值线段树先把总逆序对求出来,接着 ...

  4. bzoj3295[Cqoi2011]动态逆序对 树套树

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

  5. 2018.07.01 BZOJ3295: [Cqoi2011]动态逆序对(带修主席树)

    3295: [Cqoi2011]动态逆序对 **Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j& ...

  6. [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j,且 ...

  7. bzoj千题计划146:bzoj3295: [Cqoi2011]动态逆序对

    http://www.lydsy.com/JudgeOnline/problem.php?id=3295 正着删除看做倒着添加 对答案有贡献的数对满足以下3个条件: 出现时间:i<=j 权值大小 ...

  8. BZOJ3295: [Cqoi2011]动态逆序对(树状数组套主席树)

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

  9. BZOJ3295 [Cqoi2011]动态逆序对 —— CDQ分治

    题目链接:https://vjudge.net/problem/HYSBZ-3295 3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 1 ...

  10. bzoj3295: [Cqoi2011]动态逆序对(cdq分治+树状数组)

    3295: [Cqoi2011]动态逆序对 题目:传送门 题解: 刚学完cdq分治,想起来之前有一道是树套树的题目可以用cdq分治来做...尝试一波 还是太弱了...想到了要做两次cdq...然后伏地 ...

随机推荐

  1. [LeetCode] Construct Binary Tree from Inorder and Postorder Traversal 由中序和后序遍历建立二叉树

    Given inorder and postorder traversal of a tree, construct the binary tree. Note: You may assume tha ...

  2. Power Management开发的一般流程

    本文作为一个提纲挈领的介绍性文档,后面会以此展开,逐渐丰富. 开发流程 针对一个PM feature进行开发,设计模型是第一步.模型设计好之后,还要保留参数接口,可以基于这些参数针对特殊个体进行优化. ...

  3. Redis系列之(二):Redis主从同步,读写分离

    1. Redis主从同步 Redis支持主从同步.数据可以从主服务器向任意数量的从服务器上同步,同步使用的是发布/订阅机制. 2. 配置主从同步 Mater Slave的模式,从Slave向Maste ...

  4. CSS Hack技术介绍及常用的Hack技巧集锦

    一.什么是CSS Hack? 不同的浏览器对CSS的解析结果是不同的,因此会导致相同的CSS输出的页面效果不同,这就需要CSS Hack来解决浏览器局部的兼容性问题.而这个针对不同的浏览器写不同的CS ...

  5. Codeforces #364 DIV2

      ~A题 A. Cards time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  6. Shiro-集成Spring

    集成Spring 加入Spring 和Shiro的jar 包 配置Spring 及SpringMVC 参照:1.3.2\shiro-root-1.3.2-source-release\shiro-ro ...

  7. bzoj 4003

    左偏树... 打两个标记...和线段树一样,先下放cheng再下放*. 每回合并子树就行了. #include<iostream> #include<cstdio> #incl ...

  8. Zabbix监控mysql performance

    介绍 zabbix监控mysql性能,使用zabbix自带的mysql监控模板,可以监控以下内容OPS(增删改查).mysql慢查询数量.mysql请求\响应流量带宽 配置 新建mysql监控用户 G ...

  9. 帝国cms内容页调用缩略图的原始尺寸图片

    在发布文章上传标题图片时,勾选"生成缩略图",将生成原图和对应的缩略图 原图的链接为[!--titlepic--]:/d/file/anlizhanshi/2016-11-25/8 ...

  10. 谷歌浏览器,火狐浏览器,ie浏览器解析顺序

    谷歌(版本 55.0.2883.87 m),火狐(48.0.2),ie(11.576.14393.0)对三个浏览器简单的进行了一下试验发现,谷歌浏览器是等到html全部解析完毕之后才开始渲染,而另外两 ...