【Luogu】P1393动态逆序对(树套树)
树套树。
每次删掉x的时候会减去1到x-1里比x位置的数大的数和它构成的逆序对,以及x+1到n里比x位置的数小的数和它构成的逆序对。
顺带一提我发现平衡树insert的时候不是要splay一下嘛
如果改成每插入50个splay一下会快的飞起
我这道题就是这么卡过去的23333
放上代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<algorithm>
#define mid ((l+r)>>1)
#define left (rt<<1)
#define right (rt<<1|1)
#define lson l,mid,left
#define rson mid+1,r,right
using namespace std;
int CNT; inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} int root[];
int q[]; struct Splay{
struct Node{
int size,sum,e[],val,fa;
}tree[];
int point,tot;
Splay(){ point=tot=; }
inline int iden(int x){ return x==tree[tree[x].fa].e[]; }
inline void connect(int x,int fa,int how){ tree[x].fa=fa; tree[fa].e[how]=x; }
inline void update(int x){
tree[x].size=tree[x].sum;
if(tree[x].e[]) tree[x].size+=tree[tree[x].e[]].size;
if(tree[x].e[]) tree[x].size+=tree[tree[x].e[]].size;
}
void rotate(int x,int rt){
int y=tree[x].fa; int r=tree[y].fa;
if(root[rt]==y) root[rt]=x;
int sony=iden(x),sonr=iden(y);
int b=tree[x].e[sony^];
connect(b,y,sony);
connect(y,x,sony^);
connect(x,r,sonr);
update(y);update(x);
}
void splay(int pos,int to,int rt){
to=tree[to].fa;
while(tree[pos].fa!=to){
if(tree[tree[pos].fa].fa==to) rotate(pos,rt);
else
if(iden(pos)==iden(tree[pos].fa)){ rotate(tree[pos].fa,rt); rotate(pos,rt); }
else{ rotate(pos,rt); rotate(pos,rt); }
}
}
int create(int val,int fa){
tree[++tot].val=val; tree[tot].sum=tree[tot].size=; tree[tot].fa=fa;
return tot;
}
int find(int val,int rt){
int now=root[rt];
while(){
if(!now) return ;
if(tree[now].val==val){
splay(now,root[rt],rt);
return now;
}
int nxt=val>tree[now].val?:;
if(!tree[now].e[nxt]) return ;
now=tree[now].e[nxt];
}
}
int build(int val,int rt){
point++;
if(!root[rt]){
root[rt]=create(val,);
return root[rt];
}
int now=root[rt];
while(){
tree[now].size++;
if(tree[now].val==val){
tree[now].sum++;
return now;
}
int nxt=val>tree[now].val?:;
if(!tree[now].e[nxt]){
int p=create(val,now);
connect(p,now,nxt);
return p;
}
now=tree[now].e[nxt];
}
}
void insert(int val,int rt){
int p=build(val,rt);
if((++CNT)%==){
splay(p,root[rt],rt);
CNT=;
}
}
void dele(int x){
tree[x].e[]=tree[x].e[]=;
if(x==tot) tot--;
}
void pop(int val,int rt){
int deal=find(val,rt);
if(!deal) return;
point--;
if(tree[deal].sum>){ tree[deal].sum--; tree[deal].size--; return;}
if(!tree[deal].e[]){
root[rt]=tree[deal].e[];
tree[root[rt]].fa=;
}
else{
int le=tree[deal].e[];
while(tree[le].e[]) le=tree[le].e[];
splay(le,tree[deal].e[],rt);
int ri=tree[deal].e[];
connect(ri,le,); tree[le].fa=;
root[rt]=le;
update(le);
}
dele(deal);
}
int rank(int val,int rt){
int ans=,now=root[rt];
while(){
if(!now) return ans;
if(tree[now].val==val){
ans+=tree[tree[now].e[]].size;
return ans;
}
if(val<tree[now].val) now=tree[now].e[];
else{
ans+=tree[tree[now].e[]].size+tree[now].sum;
now=tree[now].e[];
}
}
}
int arank(int val,int rt){
int ans=,now=root[rt];
while(){
if(!now) return ans;
if(tree[now].val==val){
ans+=tree[tree[now].e[]].size;
return ans;
}
if(val<tree[now].val){
ans+=tree[tree[now].e[]].size+tree[now].sum;
now=tree[now].e[];
}
else now=tree[now].e[];
}
}
int ask(int val,int rt,int opt){
if(opt==) return arank(val,rt);
else return rank(val,rt);
}
}s; void build(int l,int r,int rt){
for(int i=l;i<=r;++i) s.insert(q[i],rt);
if(l==r) return;
build(lson);
build(rson);
} int query(int from,int to,int val,int l,int r,int rt,int opt){
if(from>to) return ;
if(from<=l&&to>=r) return s.ask(val,rt,opt);
int cnt=;
if(from<=mid) cnt+=query(from,to,val,lson,opt);
if(to>mid) cnt+=query(from,to,val,rson,opt);
return cnt;
} void Delete(int o,int val,int l,int r,int rt){
s.pop(val,rt);
if(l==r) return;
if(o<=mid) Delete(o,val,lson);
else Delete(o,val,rson);
} int ans; int main(){
int n=read(),m=read();
for(int i=;i<=n;++i) q[i]=read();
build(,n,);
for(int i=;i<=n;++i) ans+=query(,i-,q[i],,n,,);
printf("%d",ans);
for(int i=;i<=m;++i){
int pos=read();
ans-=query(,pos-,q[pos],,n,,);
ans-=query(pos+,n,q[pos],,n,,);
printf(" %d",ans);
Delete(pos,q[pos],,n,);
}
return ;
}
【Luogu】P1393动态逆序对(树套树)的更多相关文章
- 【BZOJ3295】动态逆序对(线段树,树状数组)
[BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...
- BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组
BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一 ...
- P1393 动态逆序对
题目 P1393 动态逆序对 做题前写篇博客是个好方法 做法 题目规定仅有删除,给每个位置标个号,逆序对+时间轴,显然这是个三维偏序 很久没做过\(cdq\)了,就当模板题讲一下: 按删除的先后顺序为 ...
- [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j,且 ...
- bzoj3295: [Cqoi2011]动态逆序对(cdq分治+树状数组)
3295: [Cqoi2011]动态逆序对 题目:传送门 题解: 刚学完cdq分治,想起来之前有一道是树套树的题目可以用cdq分治来做...尝试一波 还是太弱了...想到了要做两次cdq...然后伏地 ...
- [bzoj3295][Cqoi2011]动态逆序对_主席树
动态逆序对 bzoj-3295 Cqoi-2011 题目大意:题目链接. 注释:略. 想法:直接建立主席树. 由于是一个一个删除,所以我们先拿建立好的root[n]的权值线段树先把总逆序对求出来,接着 ...
- 洛谷P1393 动态逆序对(CDQ分治)
传送门 题解 听别人说这是洛谷用户的双倍经验啊……然而根本没有感觉到……因为另外的那题我是用树状数组套主席树做的……而且莫名其妙感觉那种方法思路更清晰(虽然码量稍稍大了那么一点点)……感谢Candy大 ...
- BZOJ3295/Luogu3157 [CQOI2011]动态逆序对 (CDQ or 树套树 )
/* Dear friend, wanna learn CDQ? As a surprice, this code is totally wrong. You may ask, then why yo ...
- bzoj3295 洛谷P3157、1393 动态逆序对——树套树
题目:bzoj3295 https://www.lydsy.com/JudgeOnline/problem.php?id=3295 洛谷 P3157(同一道题) https://www.luogu.o ...
随机推荐
- JS权威指南-概述学习
<script src="/javascripts/application.js" type="text/javascript" charset=&quo ...
- 【数据分析 R语言实战】学习笔记 第八章 方差分析与R实现
方差分析泛应用于商业.经济.医学.农业等诸多领域的数量分析研究中.例如商业广告宣传方面,广告效果可能会受广告式.地区规模.播放时段.播放频率等多个因素的影响,通过方差分析研究众多因素中,哪些是主要的以 ...
- UVA Live 3713 Astronauts (2-SAT)
用布尔变量表示状态,把限制条件转化为XνY的形式以后跑2SAT,根据变量取值输出方案. #include<bits/stdc++.h> using namespace std; ; #de ...
- python_108_格式化字符串format函数
#通过关键字映射 print('I am {name},age {age}'.format(name='qiqi齐',age=18))#I am qiqi齐,age 18 dictory={'name ...
- 【转载】WPF DataGrid 性能加载大数据
作者:过客非归 来源:CSDN 原文:https://blog.csdn.net/u010265681/article/details/76651725 WPF(Windows Presentatio ...
- Vue之父子组件的通信
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- SSH整合JAR包详解
如果要使用连接池,添加JAR : c3p0-0.9.1.2.jar
- mac拷贝原版和权限修复的命令行工具
建议直接从安装盘中用命令复制,因为上传的kext权限会变,导致签名失败. 假定安装盘盘符是install_osx: sudo cp -R /Volumes/install_osx/S*/L*/E*/A ...
- 268. Missing Number@python
Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missin ...
- database---many to many relationships(多对多关系型数据库)
Many to many Relationships A many-to-many relationship occurs when multiple records in a table are a ...