题目链接

  树套树。

  每次删掉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动态逆序对(树套树)的更多相关文章

  1. 【BZOJ3295】动态逆序对(线段树,树状数组)

    [BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...

  2. BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组

    BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一 ...

  3. P1393 动态逆序对

    题目 P1393 动态逆序对 做题前写篇博客是个好方法 做法 题目规定仅有删除,给每个位置标个号,逆序对+时间轴,显然这是个三维偏序 很久没做过\(cdq\)了,就当模板题讲一下: 按删除的先后顺序为 ...

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

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

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

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

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

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

  7. 洛谷P1393 动态逆序对(CDQ分治)

    传送门 题解 听别人说这是洛谷用户的双倍经验啊……然而根本没有感觉到……因为另外的那题我是用树状数组套主席树做的……而且莫名其妙感觉那种方法思路更清晰(虽然码量稍稍大了那么一点点)……感谢Candy大 ...

  8. BZOJ3295/Luogu3157 [CQOI2011]动态逆序对 (CDQ or 树套树 )

    /* Dear friend, wanna learn CDQ? As a surprice, this code is totally wrong. You may ask, then why yo ...

  9. bzoj3295 洛谷P3157、1393 动态逆序对——树套树

    题目:bzoj3295 https://www.lydsy.com/JudgeOnline/problem.php?id=3295 洛谷 P3157(同一道题) https://www.luogu.o ...

随机推荐

  1. Android的开机流程及对应源码位置分析

    1.系统引导bootloader 1)源码:bootable/bootloader/* 2)说明:加电后,CPU将先执行bootloader程序,此处有三种选择 a)开机按Camera+Power启动 ...

  2. 【extjs6学习笔记】0.0 准备

    1.下载ExtJS 6 下面是Ext JS 6正式版的GPL版本下载地址 https://www.sencha.com/legal/gpl/ 2.下载sencha cmd 安装完成后,命令行运行出现以 ...

  3. vue+element ui项目总结点(二)table合计栏目,按照起始年份--截止年份 插入数据并向后追加数据以最后一条年份+1

    1.oninput 事件在用户输入时触发; <template> <div class="test_box"> <p>hell,你好</p ...

  4. COGS 36. 求和问题

    时间限制:1.2 s   内存限制:128 MB [问题描述]     在一个长度为n的整数数列中取出连续的若干个数,并求它们的和. [输入格式]     输入由若干行组成,第一行有一个整数n    ...

  5. 如何诊断 11.2 集群节点驱逐问题 (文档 ID 1674872.1)

    适用于: Oracle Database - Enterprise Edition - 版本 11.2.0.1 到 11.2.0.2 [发行版 11.2]本文档所含信息适用于所有平台 用途 这篇文档提 ...

  6. Codeforces Round #317 div2 E div1 C CNF 2 (图论,匹配)

      CNF 2 'In Boolean logic, a formula is in conjunctive normal form (CNF) or clausal normal form if i ...

  7. 基本编程题 --python

    1.让Python帮你随机选一个饮品吧! import random listC = ['加多宝', '雪碧', '可乐', '勇闯天涯', '椰子汁'] print(random.choices(l ...

  8. python之路——递归函数

    阅读目录 楔子 初识递归 再谈递归 递归函数与三级菜单 递归函数与二分查找算法 楔子 在讲今天的内容之前,我们先来讲一个故事,讲的什么呢?从前有座山,山里有座庙,庙里有个老和尚讲故事,讲的什么呢?从前 ...

  9. 朴素贝叶斯分类<转载>

    转自http://www.cnblogs.com/leoo2sk/archive/2010/09/17/naive-bayesian-classifier.html 0.写在前面的话 我个人一直很喜欢 ...

  10. python爬虫---实现项目(四) 用BeautifulSoup分析新浪新闻数据

    这次只演示了,如何在真实项目内用到BeautifulSoup库来解析网页,而新浪的新闻是ajax加载过来的数据,在这里我们只演示解析部分数据(具体反扒机制没做分析). 代码地址:https://git ...