BZOJ - 2141 排队 (动态逆序对,区间线段树套权值线段树)
交换两个数的位置,只有位于两个数之间的部分会受到影响,因此只需要考虑两个数之间有多少数对a[l]和a[r]产生的贡献发生了变化即可。
感觉像是个带修改的二维偏序问题。(修改点$(x,y)$的值,维护和查询位于$(x_1,y_1)$与$(x_2,y_2)$之间的点的个数)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e4+,inf=0x3f3f3f3f;
int n,m,n2,rt[N<<],ls[N*],rs[N*],sum[N*],tot,a[N],b[N],ans;
#define lson (u<<1)
#define rson (u<<1|1)
#define mid ((l+r)>>1)
void upd2(int p,int x,int& u,int l=,int r=n2) {
if(!u)u=++tot;
sum[u]+=x;
if(l==r)return;
p<=mid?upd2(p,x,ls[u],l,mid):upd2(p,x,rs[u],mid+,r);
}
int qry2(int L,int R,int& u,int l=,int r=n2) {
if(l>=L&&r<=R)return sum[u];
if(l>R||r<L)return ;
return qry2(L,R,ls[u],l,mid)+qry2(L,R,rs[u],mid+,r);
}
void upd(int p,int x,int dx,int u=,int l=,int r=n) {
upd2(x,dx,rt[u]);
if(l==r)return;
p<=mid?upd(p,x,dx,lson,l,mid):upd(p,x,dx,rson,mid+,r);
}
int qry(int L,int R,int L2,int R2,int u=,int l=,int r=n) {
if(l>=L&&r<=R)return qry2(L2,R2,rt[u]);
if(l>R||r<L)return ;
return qry(L,R,L2,R2,lson,l,mid)+qry(L,R,L2,R2,rson,mid+,r);
}
int main() {
scanf("%d",&n);
for(int i=; i<=n; ++i)scanf("%d",&a[i]);
for(int i=; i<=n; ++i)b[i]=a[i];
sort(b+,b++n),n2=unique(b+,b++n)-(b+);
for(int i=; i<=n; ++i)a[i]=lower_bound(b+,b++n2,a[i])-b;
for(int i=; i<=n; ++i)ans+=qry(,n,a[i]+,n2),upd(i,a[i],);
printf("%d\n",ans);
scanf("%d",&m);
while(m--) {
int l,r;
scanf("%d%d",&l,&r);
if(l>r)swap(l,r);
if(l==r||a[l]==a[r]);
else {
if(a[l]<a[r])ans+=qry(l+,r-,a[l]+,a[r])+qry(l+,r-,a[l],a[r]-)+;
else ans-=qry(l+,r-,a[r]+,a[l])+qry(l+,r-,a[r],a[l]-)+;
upd(l,a[l],-),upd(l,a[r],);
upd(r,a[r],-),upd(r,a[l],);
swap(a[l],a[r]);
}
printf("%d\n",ans);
}
return ;
}
还有理论上能够AC的线段树套treap的版本,可惜常数太大TLE了~QAQ~
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e4+,inf=0x3f3f3f3f;
int n,m,n2,rt[N<<],ch[N*][],val[N*],siz[N*],rd[N*],tot,a[N],b[N],ans;
#define lson (u<<1)
#define rson (u<<1|1)
#define mid ((l+r)>>1)
void pu(int u) {siz[u]=siz[ch[u][]]+siz[ch[u][]]+;}
int newnode(int x) {int u=++tot; ch[u][]=ch[u][]=,siz[u]=,val[u]=x,rd[u]=rand(); return u;}
void rot(int& u,int f) {
int v=ch[u][f];
ch[u][f]=ch[v][f^],ch[v][f^]=u;
pu(u),pu(v),u=v;
}
void ins(int& u,int x) {
if(!u) {u=newnode(x); return;}
int f=x>val[u];
ins(ch[u][f],x);
if(rd[ch[u][f]]>rd[u])rot(u,f);
if(u)pu(u);
}
void del(int& u,int x) {
if(!u)return;
if(val[u]==x) {
if(!ch[u][]||!ch[u][])u=ch[u][]|ch[u][];
else {
int f=rd[ch[u][]]>rd[ch[u][]];
rot(u,f),del(ch[u][f^],x);
}
} else del(ch[u][x>val[u]],x);
if(u)pu(u);
}
int lb(int u,int x) {
int ret=;
for(; u; u=ch[u][x>val[u]])if(val[u]>=x)ret=val[u];
return ret;
}
int ub(int u,int x) {
int ret=;
for(; u; u=ch[u][x>=val[u]])if(val[u]>x)ret=val[u];
return ret;
}
int rnk(int u,int x) {
int ret=;
for(; u; u=ch[u][x>val[u]])if(x>val[u])ret+=siz[ch[u][]]+;
return ret+;
}
int sum(int u,int l,int r) {return l>r?:rnk(u,ub(u,r))-rnk(u,lb(u,l));}
void upd(int p,int x,int dx,int u=,int l=,int r=n) {
dx==?ins(rt[u],x):del(rt[u],x);
if(l==r)return;
p<=mid?upd(p,x,dx,lson,l,mid):upd(p,x,dx,rson,mid+,r);
}
int qry(int L,int R,int L2,int R2,int u=,int l=,int r=n) {
if(l>=L&&r<=R)return sum(rt[u],L2,R2);
if(l>R||r<L)return ;
return qry(L,R,L2,R2,lson,l,mid)+qry(L,R,L2,R2,rson,mid+,r);
}
void build(int u=,int l=,int r=n) {
ins(rt[u],~inf),ins(rt[u],inf);
if(l==r)return;
build(lson,l,mid),build(rson,mid+,r);
}
int main() {
srand(time());
scanf("%d",&n);
for(int i=; i<=n; ++i)scanf("%d",&a[i]);
for(int i=; i<=n; ++i)b[i]=a[i];
sort(b+,b++n),n2=unique(b+,b++n)-(b+);
for(int i=; i<=n; ++i)a[i]=lower_bound(b+,b++n2,a[i])-b;
build();
for(int i=; i<=n; ++i)ans+=qry(,n,a[i]+,n2),upd(i,a[i],);
printf("%d\n",ans);
scanf("%d",&m);
while(m--) {
int l,r;
scanf("%d%d",&l,&r);
if(l>r)swap(l,r);
if(l==r||a[l]==a[r]);
else {
if(a[l]<a[r])ans+=qry(l+,r-,a[l]+,a[r])+qry(l+,r-,a[l],a[r]-)+;
else ans-=qry(l+,r-,a[r]+,a[l])+qry(l+,r-,a[r],a[l]-)+;
upd(l,a[l],-),upd(l,a[r],);
upd(r,a[r],-),upd(r,a[l],);
swap(a[l],a[r]);
}
printf("%d\n",ans);
}
return ;
}
后续:我把treap的区间求和方式改了稍微改了一下,卡时过掉了~~
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e4+,inf=0x3f3f3f3f;
int n,m,n2,rt[N<<],ch[N*][],val[N*],siz[N*],rd[N*],tot,a[N],b[N],ans;
#define lson (u<<1)
#define rson (u<<1|1)
#define mid ((l+r)>>1)
void pu(int u) {siz[u]=siz[ch[u][]]+siz[ch[u][]]+;}
int newnode(int x) {int u=++tot; ch[u][]=ch[u][]=,siz[u]=,val[u]=x,rd[u]=rand(); return u;}
void rot(int& u,int f) {
int v=ch[u][f];
ch[u][f]=ch[v][f^],ch[v][f^]=u;
pu(u),pu(v),u=v;
}
void ins(int& u,int x) {
if(!u) {u=newnode(x); return;}
int f=x>val[u];
ins(ch[u][f],x);
if(rd[ch[u][f]]>rd[u])rot(u,f);
if(u)pu(u);
}
void del(int& u,int x) {
if(!u)return;
if(val[u]==x) {
if(!ch[u][]||!ch[u][])u=ch[u][]|ch[u][];
else {
int f=rd[ch[u][]]>rd[ch[u][]];
rot(u,f),del(ch[u][f^],x);
}
} else del(ch[u][x>val[u]],x);
if(u)pu(u);
}
int lb(int u,int x) {
int ret=;
for(; u; u=ch[u][x>val[u]])if(x>val[u])ret+=siz[ch[u][]]+;
return ret;
}
int ub(int u,int x) {
int ret=;
for(; u; u=ch[u][x>=val[u]])if(x>=val[u])ret+=siz[ch[u][]]+;
return ret;
}
int sum(int u,int l,int r) {return ub(u,r)-lb(u,l);}
void upd(int p,int x,int dx,int u=,int l=,int r=n) {
dx==?ins(rt[u],x):del(rt[u],x);
if(l==r)return;
p<=mid?upd(p,x,dx,lson,l,mid):upd(p,x,dx,rson,mid+,r);
}
int qry(int L,int R,int L2,int R2,int u=,int l=,int r=n) {
if(l>=L&&r<=R)return sum(rt[u],L2,R2);
if(l>R||r<L)return ;
return qry(L,R,L2,R2,lson,l,mid)+qry(L,R,L2,R2,rson,mid+,r);
}
int main() {
srand(time());
scanf("%d",&n);
for(int i=; i<=n; ++i)scanf("%d",&a[i]);
for(int i=; i<=n; ++i)b[i]=a[i];
sort(b+,b++n),n2=unique(b+,b++n)-(b+);
for(int i=; i<=n; ++i)a[i]=lower_bound(b+,b++n2,a[i])-b;
for(int i=; i<=n; ++i)ans+=qry(,n,a[i]+,n2),upd(i,a[i],);
printf("%d\n",ans);
scanf("%d",&m);
while(m--) {
int l,r;
scanf("%d%d",&l,&r);
if(l>r)swap(l,r);
if(l==r||a[l]==a[r]);
else {
if(a[l]<a[r])ans+=qry(l+,r-,a[l]+,a[r])+qry(l+,r-,a[l],a[r]-)+;
else ans-=qry(l+,r-,a[r]+,a[l])+qry(l+,r-,a[r],a[l]-)+;
upd(l,a[l],-),upd(l,a[r],);
upd(r,a[r],-),upd(r,a[l],);
swap(a[l],a[r]);
}
printf("%d\n",ans);
}
return ;
}
BZOJ - 2141 排队 (动态逆序对,区间线段树套权值线段树)的更多相关文章
- 【bzoj3065】带插入区间K小值 替罪羊树套权值线段树
题目描述 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它的随从伏特提出 ...
- Bzoj 2141: 排队 分块,逆序对,树状数组
2141: 排队 Time Limit: 4 Sec Memory Limit: 259 MBSubmit: 1310 Solved: 517[Submit][Status][Discuss] D ...
- [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)
[BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...
- BZOJ2141排队——树状数组套权值线段树(带修改的主席树)
题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...
- luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)
带修改区间K大值 这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做 时空都是$O(nlog^2n)$的(如果离散化了的话 ...
- CF1093E Intersection of Permutations 树状数组套权值线段树
\(\color{#0066ff}{ 题目描述 }\) 给定整数 \(n\) 和两个 \(1,\dots,n\) 的排列 \(a,b\). \(m\) 个操作,操作有两种: \(1\ l_a\ r_a ...
- Dynamic Rankings(树状数组套权值线段树)
Dynamic Rankings(树状数组套权值线段树) 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[ ...
- 主席树 【权值线段树】 && 例题K-th Number POJ - 2104
一.主席树与权值线段树区别 主席树是由许多权值线段树构成,单独的权值线段树只能解决寻找整个区间第k大/小值问题(什么叫整个区间,比如你对区间[1,8]建立一颗对应权值线段树,那么你不能询问区间[2,5 ...
- BZOJ_3685_普通van Emde Boas树_权值线段树
BZOJ_3685_普通van Emde Boas树_权值线段树 Description 设计数据结构支持: 1 x 若x不存在,插入x 2 x 若x存在,删除x 3 输出当前最小值,若不存 ...
随机推荐
- 外部类与main方法笔记
外部类 1. 外部public class只能有一个 2. 外部类只能有两种访问控制级别: public 和默认 3. 一个文件中,可以有多个public class,即外部类为public,还可以有 ...
- springboot学习(三)——使用HttpMessageConverter进行http序列化和反序列化
以下内容,如有问题,烦请指出,谢谢! 对象的序列化/反序列化大家应该都比较熟悉:序列化就是将object转化为可以传输的二进制,反序列化就是将二进制转化为程序内部的对象.序列化/反序列化主要体现在程序 ...
- Spring中Bean管理的常用注解
在Spring中,主要用于管理bean的注解分为四大类:1.用于创建对象.2.用于给对象的属性注入值.3.用于改变作用的范围.4.用于定义生命周期.这几个在开发中经常接触到,也可以说每天都会遇见.其中 ...
- php异常处理笔记
<?php header("Content-type:text/html;charset=utf-8"); // try // { // //业务处理 错误时抛出异常. // ...
- Hibernate -- 操作持久化对象
知识点2: session概述 Session 接口是 Hibernate 向应用程序提供的操纵对数据库的最主要的接口,它提供了基本的保存,更新, 删除和加载Java对象的方法. 知识点3:理解ses ...
- BZOJ4456/UOJ184 [Zjoi2016]旅行者
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- centOS7.4 thinkPHP nginx 支持pathinfo和rewrite
server { listen 80; server_name www.demo.com mayifanx.com; root /data/www/demo; index index.php inde ...
- LeetCode第[50]题(Java):Pow(x, n)
题目:求x的n次幂 难度:Medium 题目内容: Implement pow(x, n), which calculates x raised to the power n (xn). 翻译: 实现 ...
- mysql数据库优化课程---12、mysql嵌套和链接查询
mysql数据库优化课程---12.mysql嵌套和链接查询 一.总结 一句话总结:查询user表中存在的所有班级的信息? in distinct mysql> select * from cl ...
- spring3: 对JDBC的支持 之 关系数据库操作对象化
7.3.1 概述 所谓关系数据库对象化其实就是用面向对象方式表示关系数据库操作,从而可以复用. Spring JDBC框架将数据库操作封装为一个RdbmsOperation,该对象是线程安全的.可复 ...