bzoj2141_排队
Posted zxcoder
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2141_排队相关的知识,希望对你有一定的参考价值。
题意
给定\(n\)个数,每次交换两个数,输出交换后的逆序数。
分析
- 交换两个数只会影响到对应区间内的逆序数,具体为减少区间\([l+1,r-1]\)中比\(a[r]\)大的数的个数,增加比\(a[r]\)大的数的个数,减少比大的数的个数,\(a[l]\)增加比\(a[l]\)小的数的个数。
- 转化为单点修改+查询区间值域个数,树套树。
- 思路不难想,写完调了一年,注意几个点
- 外层bit大小是的是序列长度n,不是离散化后的值域ns。
- 数据不保证\(l<=r\)。
- 注意相同元素。
- 最后要判断\(a[l]\)和\(a[r]\)的大小关系,除去相等。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=2e4+50;
int n,ns,m,a[N],l,r,tr[N*20],x[N],y[N],c1,c2;
struct Orz
vector<int> a;
void init()
a.clear();
int siz()
return a.size();
void add(int x)
a.push_back(x);
void work()
sort(a.begin(),a.end());
a.erase(unique(a.begin(),a.end()),a.end());
int idx(int v)
return lower_bound(a.begin(),a.end(),v)-a.begin()+1;
int val(int i)
return a[i-1];
orz;
struct HJT
#define mid (l+r)/2
int tot,sum[N*200],ls[N*200],rs[N*200];
void update(int &x,int l,int r,int v,int add)
if(!x)
x=++tot;
sum[x]+=add;
if(l<r)
if(v<=mid)
update(ls[x],l,mid,v,add);
else
update(rs[x],mid+1,r,v,add);
int query(int l,int r,int k)
if(k==0)
return 0;
if(r<=k)
int ans=0;
for(int i=1;i<=c1;i++)
ans-=sum[x[i]];
for(int i=1;i<=c2;i++)
ans+=sum[y[i]];
return ans;
if(k<=mid)
for(int i=1;i<=c1;i++)
x[i]=ls[x[i]];
for(int i=1;i<=c2;i++)
y[i]=ls[y[i]];
return query(l,mid,k);
else
int ans=0;
for(int i=1;i<=c1;i++)
ans-=sum[ls[x[i]]];
for(int i=1;i<=c2;i++)
ans+=sum[ls[y[i]]];
for(int i=1;i<=c1;i++)
x[i]=rs[x[i]];
for(int i=1;i<=c2;i++)
y[i]=rs[y[i]];
return ans+query(mid+1,r,k);
ac;
struct BIT
int lowbit(int x)
return x&(-x);
void modify(int i,int x)
int k=a[i];
while(i<=n)
ac.update(tr[i],1,ns,k,x);
i+=lowbit(i);
int query(int l,int r,int xi,int yi)
if(xi>yi)
return 0;
c1=c2=0;
for(int i=l-1;i;i-=lowbit(i))
x[++c1]=tr[i];
for(int i=r;i;i-=lowbit(i))
y[++c2]=tr[i];
int R=ac.query(1,ns,yi);
c1=c2=0;
for(int i=l-1;i;i-=lowbit(i))
x[++c1]=tr[i];
for(int i=r;i;i-=lowbit(i))
y[++c2]=tr[i];
int L=ac.query(1,ns,xi-1);
return R-L;
bit;
int main()
// freopen("in.txt","r",stdin);
scanf("%d",&n);
orz.init();
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
orz.add(a[i]);
orz.work();
ns=orz.siz();
int ans=0;
for(int i=1;i<=n;i++)
a[i]=orz.idx(a[i]);
bit.modify(i,1);
ans+=bit.query(1,i,a[i]+1,ns);
printf("%d\n",ans);
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d%d",&l,&r);
if(l>r)
swap(l,r);
if(l==r)
printf("%d\n",ans);
continue;
if(r-l>=2)
int ta=bit.query(l+1,r-1,a[r]+1,ns);
int tb=bit.query(l+1,r-1,a[l]+1,ns);
int tc=bit.query(l+1,r-1,1,a[r]-1);
int td=bit.query(l+1,r-1,1,a[l]-1);
ans-=ta;
ans+=tc;
ans+=tb;
ans-=td;
if(a[l]<a[r])
ans++;
else if(a[l]>a[r])
ans--;
bit.modify(l,-1);
bit.modify(r,-1);
swap(a[l],a[r]);
bit.modify(l,1);
bit.modify(r,1);
printf("%d\n",ans);
return 0;
以上是关于bzoj2141_排队的主要内容,如果未能解决你的问题,请参考以下文章