【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 ...
随机推荐
- 关于搭建系统直播和Thinkphp的杂谈(持续更新)
Q:Access denied for user 'root'@'localhost' 错误 A:第一种:配置文件中把数据库的用户名密码再改一遍,把runtime里的文件删除 第二种:修改syste ...
- PHP-PHPExcel用法详解
以下文章来源:diandian_520 http://blog.csdn.net/diandian_520/article/details/7827038 1.header header(" ...
- JSP serverlet区别与联系
jsp是html包含java servlet是java包含html jsp请求到tomcat---tomcat封装了jsp到servlet实现. 所以jsp请求时候,会自动创建session 而不用在 ...
- Jsoup获取全国地区数据(省市县镇村)(续) 纯干货分享
前几天给大家分享了一下,怎么样通过jsoup来从国家统计局官网获取全国省市县镇村的数据.错过的朋友请点击这里.上文说到抓取到数据以后,我们怎么转换成我们想要格式呢?哈哈,解析方式可能很简单,但是有一点 ...
- 洛谷 P1449 后缀表达式
题目描述 所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级). 如:3*(5–2)+7对应 ...
- Fixed table
废话不多说,直接代码. <!DOCTYPE> <html> <head> <meta charset="utf-8"/> <s ...
- Mybatis Cache 缓存策略
Mybatis Cache 缓存策略 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用 ...
- 数学题 追及相遇—HDOJ1275 人傻需要多做题
两车追及或相遇问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- mysql 外键关联
mysql 外键关联 什么是外键:外键是一个特殊的索引,用于关联两个表,只能是指定内容. 如我将新建一个daka的表,然后将此表的class_id 与另外一个class的表的cid字段关联 class ...
- 单源最短路SPFA
#include<iostream> #include<queue> #include<cstring> #define INF 0x3f3f3f3f using ...