【CQOI2011】动态逆序对 BZOJ3295
Description
Input
Output
Sample Input
1
5
3
4
2
5
1
4
2
Sample Output
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的更多相关文章
- 【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治
[BZOJ3295][Cqoi2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依 ...
- bzoj3295 [Cqoi2011]动态逆序对 cdq+树状数组
[bzoj3295][Cqoi2011]动态逆序对 2014年6月17日4,7954 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数. ...
- [bzoj3295][Cqoi2011]动态逆序对_主席树
动态逆序对 bzoj-3295 Cqoi-2011 题目大意:题目链接. 注释:略. 想法:直接建立主席树. 由于是一个一个删除,所以我们先拿建立好的root[n]的权值线段树先把总逆序对求出来,接着 ...
- bzoj3295[Cqoi2011]动态逆序对 树套树
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5987 Solved: 2080[Submit][Sta ...
- 2018.07.01 BZOJ3295: [Cqoi2011]动态逆序对(带修主席树)
3295: [Cqoi2011]动态逆序对 **Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j& ...
- [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j,且 ...
- bzoj千题计划146:bzoj3295: [Cqoi2011]动态逆序对
http://www.lydsy.com/JudgeOnline/problem.php?id=3295 正着删除看做倒着添加 对答案有贡献的数对满足以下3个条件: 出现时间:i<=j 权值大小 ...
- BZOJ3295: [Cqoi2011]动态逆序对(树状数组套主席树)
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 7465 Solved: 2662[Submit][Sta ...
- BZOJ3295 [Cqoi2011]动态逆序对 —— CDQ分治
题目链接:https://vjudge.net/problem/HYSBZ-3295 3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 1 ...
- bzoj3295: [Cqoi2011]动态逆序对(cdq分治+树状数组)
3295: [Cqoi2011]动态逆序对 题目:传送门 题解: 刚学完cdq分治,想起来之前有一道是树套树的题目可以用cdq分治来做...尝试一波 还是太弱了...想到了要做两次cdq...然后伏地 ...
随机推荐
- [LeetCode] Excel Sheet Column Number 求Excel表列序号
Related to question Excel Sheet Column Title Given a column title as appear in an Excel sheet, retur ...
- 从点云到网格(三)Poisson重建
Possion重建是Kazhdan等2006年提出的网格重建方法[1].Possion重建的输入是点云及其法向量,输出是三维网格.Poisson有公开的源代码[2].PCL中也有Poisson的实现. ...
- 撸一段 SQL ? 还是撸一段代码?
记得刚入公司带我的研发哥们能写一手漂亮的 SQL,搜索准确.执行快.效率高. 配合Web项目中的查询展示数据的需求,基本是分分钟完成任务. 那段时间基本是仰视的态度,每天都去讨教一点手写 SQL 的要 ...
- .NET跨平台之旅:在Linux上以本地机器码(native)运行ASP.NET Core站点
在将“.NET跨平台之旅”示例站点 about.cnblogs.com 从 ASP.NET 5 RC1 升级至 ASP.NET Core 1.0 (博文链接)之后,我们有一个难以抗拒的冲动 —— 体验 ...
- Socket通信类
package com.imooc; import java.io.BufferedReader; import java.io.IOException; import java.io.InputSt ...
- ubuntu中phpmyadmin密码忘记
在安装mysql时,默认只让你设置了root的密码,如果root的密码忘记,处理办法如下 第一步: 这时你需要进入/etc/mysql目录下,然后sudo vim/vi debian.cnf查看里面的 ...
- 使用DataTable更新数据库
简例: string connStr = string.Format("Driver={1}Microsoft Access Driver (*.mdb){2};DBQ={0};" ...
- bootstrap 日期控件 bootstrap-datepicker
http://www.bootcss.com/p/bootstrap-datetimepicker/
- wxpython绘制折线图
environment:win10 + eclipse + pydev + python2.7.11 + wxpython3.0.2 code sample: #!/usr/bin/env pytho ...
- C#基础强化-继承与多态
/** 特性: 单根性:一个子类只能有一个父类 传递性:爷爷类 爹类 儿子类 里氏转换 1.子类可以赋值给父类 2.如果父类装的是子类对象,则可以将这个父类转换为对应的子类 ...