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 输出当前最小值,若不存 ...
随机推荐
- MySQL-5.7创建及查看数据库表
1.创建数据库表的三种语句 创建一个新表: CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name (create_definition,...) [tab ...
- jQuery上下切换带缩略图的焦点图
在线演示 本地下载
- c语言的按位运算符
& 按位与 | 按位或 ^ 按位异或 1. 按位与运算 按位与运算符"&"是双目运算符.其功能是参与运算的两数各对应的二进位相与.只有对应的两个二进位均为1时,结果 ...
- java-json与js-json转化
js中将字符串转换成json的三种方式http://www.jb51.net/article/25987.htm JAVA对象转换为JSON字符串 http://blog.163.com/zzf_fl ...
- [mongodb] MMAP 和wiredTiger 的比较
mongodb 现在有两款存储引擎 MMAPv1 和 WireTiger,当然了除了这两款存储引擎还有其他的存储引擎了. 如: 内存引擎:现在的mongodb 版本中已经有了,主要的cache 服务 ...
- Effective C++ 条款04:确定对象被使用前已经先被初始化
规则一 永远在使用对象之前将它初始化 int x = 0; const char* text = "A C-style string"; double d; std:: cin & ...
- android studio 更新Gradle版本方法
在导入其他项目时,经常由于gradle版本不一致而导致不能编译 解决方法: 第一步: 按提示点击让它下载,其实目的并不是要它下载,因为这样速度会很慢,这样做只是为了让它在本地创建相应的目录结构 第二步 ...
- Mongodb笔记(二) Index
版本:mongodb3.4; Index : 如果mongodb不能使用索引进行排序,就会将数据放入内存中进行排序,而当内存使用超过32MB时,就会报错. 在创建索引时,应确保索引的选择力,避免多余 ...
- es6 中的let,const
在es6中,let的作用和var差不多,都是用来声明变量的,但是他们之间的区别在于作用域不同,大家都知道在js中没有块级作用域,例如: for(var i=0;i<10;i++){ consol ...
- 腾讯开源手游热更新方案,Unity3D下的Lua编程
原文:http://www.sohu.com/a/123334175_355140 作者|车雄生 编辑|木环 腾讯最近在开源方面的动作不断:先是微信跨平台基础组件Mars宣布开源,腾讯手游又于近期开源 ...