[CQOI2011]动态逆序对
(又是一道树套树……自己真是玩疯了……)
(题意略)
从网上也看过题解,好像解法很多……比如CDQ+树状数组,树状数组套主席树,树状数组套平衡树……我用的是树状数组套splay。
(我会说是因为我不会写CDQ和树状数组套主席树么= =)
(不得不吐槽,为啥splay这么快= =)
也没啥可说的,我写的是在线算法,只要在删除一个元素之前统计它前面比它大的数和后面比它小的数的个数(区间求和用树状数组,统计比它小/大的数的个数用平衡树写),把答案减掉对应数值即可。
鉴于这题卡常,我就加了快读和各种inline卡常大法,然后卡了不下5次评测机才过……(COGS垃圾评测机)
顺便一提,求初始逆序对可以用归并排序or树状数组,我用的是后者。
贴个代码(貌似这是全程非递归):
#include<cstdio>
#include<cstring>
#include<algorithm>
#define siz(x) ((x)?(x)->size:0)
#define lowbit(x) ((x)&(-(x)))
using namespace std;
namespace mine{
template<class T>inline void readint(T &__x){
static int __c;
static bool __neg;
__x=;
__neg=false;
do __c=getchar();while(__c==' '||__c=='\n'||__c=='\r'||__c=='\t');
if(__c=='-'){
__neg=true;
__c=getchar();
}
for(;__c>=''&&__c<='';__c=getchar())__x=__x*+(__c^);
if(__neg)__x=-__x;
}
template<class T>inline void putint(T __x){
static int __a[],__i,__j;
static bool __neg;
__neg=__x<;
if(__neg)__x=-__x;
__i=;
do{
__a[__i++]=__x%(T)^(T);
__x/=;
}while(__x);
if(__neg)putchar('-');
for(__j=__i-;__j^-;__j--)putchar(__a[__j]);
}
}
using namespace mine;
const int maxn=;
struct node{//Splay Tree
int data,size;
node *lc,*rc,*prt;
node(int d=):data(d),size(),lc(NULL),rc(NULL),prt(NULL){}
inline void refresh(){size=siz(lc)+siz(rc)+;}
}*root[maxn]={NULL};
void add(int);
void query(int);
void build(int,int);
int qlss(int,int);
int qgrt(int,int);
void mdel(int,int);
void insert(node*,int);
node *find(int,int);
void erase(node*,int);
int rank(int,int);
int rerank(int,int);
void splay(node*,node*,int);
void lrot(node*,int);
void rrot(node*,int);
node *findmax(node*);
int n,m,a[maxn],b[maxn],c[maxn]={},x;
long long ans=0ll;
int main(){
#define MINE
#ifdef MINE
freopen("inverse.in","r",stdin);
freopen("inverse.out","w",stdout);
#endif
readint(n);
readint(m);
for(int i=;i<=n;i++){
readint(a[i]);
b[a[i]]=i;
query(a[i]);
add(a[i]);
build(i,a[i]);
}
while(m--){
putint(ans);
putchar('\n');
readint(x);
x=b[x];
ans-=(long long)qgrt(x,a[x])+(long long)qlss(n,a[x])-(long long)qlss(x-,a[x]);
mdel(x,a[x]);
}
#ifndef MINE
printf("\n--------------------DONE--------------------\n");
for(;;);
#endif
return ;
}
inline void add(int x){
while(x){
c[x]++;
x-=lowbit(x);
}
}
inline void query(int x){
while(x<=n){
ans+=c[x];
x+=lowbit(x);
}
}
inline void build(int x,int d){
while(x<=n){
insert(new node(d),x);
x+=lowbit(x);
}
}
inline int qlss(int x,int d){
int ans=;
while(x){
ans+=rank(d,x);
x-=lowbit(x);
}
return ans;
}
inline int qgrt(int x,int d){
int ans=;
while(x){
ans+=rerank(d,x);
x-=lowbit(x);
}
return ans;
}
inline void mdel(int x,int d){
while(x<=n){
erase(find(d,x),x);
x+=lowbit(x);
}
}
inline void insert(node *x,int i){
if(!root[i]){
root[i]=x;
return;
}
node *rt=root[i];
for(;;){
if(x->data<rt->data){
if(rt->lc)rt=rt->lc;
else{
rt->lc=x;
break;
}
}
else{
if(rt->rc)rt=rt->rc;
else{
rt->rc=x;
break;
}
}
}
x->prt=rt;
for(;rt;rt=rt->prt)rt->refresh();
splay(x,NULL,i);
}
inline node *find(int x,int i){
node *rt=root[i];
while(rt){
if(x==rt->data)return rt;
else if(x<rt->data)rt=rt->lc;
else rt=rt->rc;
}
return NULL;
}
inline void erase(node *x,int i){
splay(x,NULL,i);
if(x->lc){
splay(findmax(x->lc),x,i);
x->lc->rc=x->rc;
if(x->rc)x->rc->prt=x->lc;
x->lc->prt=NULL;
root[i]=x->lc;
x->lc->refresh();
}
else{
if(x->rc)x->rc->prt=NULL;
root[i]=x->rc;
}
delete x;
}
inline int rank(int x,int i){
node *rt=root[i],*y=NULL;
int ans=;
while(rt){
y=rt;
if(x<=rt->data)rt=rt->lc;
else{
ans+=siz(rt->lc)+;
rt=rt->rc;
}
}
if(y)splay(y,NULL,i);
return ans;
}
inline int rerank(int x,int i){
return siz(root[i])-rank(x+,i);
}
inline void splay(node *x,node *tar,int i){
for(node *rt=x->prt;rt!=tar;rt=x->prt){
if(rt->prt==tar){
if(x==rt->lc)rrot(rt,i);
else lrot(rt,i);
break;
}
if(rt==rt->prt->lc){
if(x==rt->lc)rrot(rt,i);
else lrot(rt,i);
rrot(x->prt,i);
}
else{
if(x==rt->rc)lrot(rt,i);
else rrot(rt,i);
lrot(x->prt,i);
}
}
}
inline void lrot(node *x,int i){
node *y=x->rc;
if(x->prt){
if(x==x->prt->lc)x->prt->lc=y;
else x->prt->rc=y;
}
else root[i]=y;
y->prt=x->prt;
x->rc=y->lc;
if(y->lc)y->lc->prt=x;
y->lc=x;
x->prt=y;
x->refresh();
y->refresh();
}
inline void rrot(node *x,int i){
node *y=x->lc;
if(x->prt){
if(x==x->prt->lc)x->prt->lc=y;
else x->prt->rc=y;
}
else root[i]=y;
y->prt=x->prt;
x->lc=y->rc;
if(y->rc)y->rc->prt=x;
y->rc=x;
x->prt=y;
x->refresh();
y->refresh();
}
inline node *findmax(node *x){
while(x->rc)x=x->rc;
return x;
}
[CQOI2011]动态逆序对的更多相关文章
- 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 ...
- bzoj3295[Cqoi2011]动态逆序对 树套树
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5987 Solved: 2080[Submit][Sta ...
- P3157 [CQOI2011]动态逆序对(树状数组套线段树)
P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...
- P3157 [CQOI2011]动态逆序对
P3157 [CQOI2011]动态逆序对 https://www.luogu.org/problemnew/show/P3157 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai&g ...
- 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 ...
- 洛谷 P3157 [CQOI2011]动态逆序对 解题报告
P3157 [CQOI2011]动态逆序对 题目描述 对于序列\(A\),它的逆序对数定义为满足\(i<j\),且\(A_i>A_j\)的数对\((i,j)\)的个数.给\(1\)到\(n ...
随机推荐
- Visual Studio无法查找或打开 PDB 文件解决办法
Visual Studio无法查找或打开 PDB 文件解决办法 用VS调试程序时,有时会在VS底部的“输出”框中提示“无法查找或打开 PDB 文件”.这该怎么解决呢? 下面,我们以VS2013为例,来 ...
- CentOS安装oracle12C
安装虚拟系统CentOS6.5,分配给至少1G的内存,其他条件适当高些,具体参考官方文档 一.安装数据库: 1.安装依赖软件包 yum install binutils -y yum install ...
- .net 应用迁移到Mono 工具 (Moma)
Mono Migration Analyzer (Moma) 是一个用于开发者使用的MS .net下开发的应用程序迁移到Mono平台的不兼容性检测工具.工具通过分析.dll或者.exe程序集的代码是否 ...
- 二、oracle pctfree和pctused详解
一.建立表时候,注意PCTFREE参数的作用 PCTFREE:为一个块保留的空间百分比,表示数据块在什么情况下可以被insert,默认是10,表示当数据块的可用空间低于10%后,就不可以被insert ...
- Gradle笔记——Gradle的简介与安装
本博客对Gradle进行一个简单的介绍,以及它的安装. Gradle介绍 Gradle是一个基于JVM的构建工具,它提供了: 像Ant一样,通用灵活的构建工具 可以切换的,基于约定的构建框架 强大的多 ...
- iOS数据库学习(1)-安装Navicat
1.下载Navicat Premium 11.0.16.dmg 已经放到百度网盘,里面有安装文件和注册机 下载链接: http://pan.baidu.com/s/1sjI64HZ 密码: 2h7q ...
- Java byte位移操作 注意事项
Java对byte 的 + - * / >> >>> << & | ^ (加,减,乘,除,右移,左移,无符号右移,位与,位或,位异或)操作,均会是首先 ...
- R You Ready?——大数据时代下优雅、卓越的统计分析及绘图环境
作者按:本文根据去年11月份CSDN举办的“大数据技术大会”演讲材料整理,最初发表于2012年2月期<程序员>杂志. 0 R 的安装
- Linux服务器管理: 系统的进程管理终止进程kill命令
在Linux中如何用kill终止进程: kill -l [root@localhost~]#kill -l 可以看到kill中有很多的 常用: -1 是重启一个进程 -9 是强制杀死进程 ...
- 8-Highcharts曲线图之对数直线图
<!DOCTYPE> <html lang='en'> <head> <title>8-Highcharts曲线图之对数直线图</title> ...