2141: 排队
Time Limit: 4 Sec Memory Limit: 259 MBSubmit: 1696 Solved: 696
[ Submit][ Status][ Discuss]
Description
排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足ihj的(i,j)数量。幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。
Input
第一行为一个正整数n,表示小朋友的数量;第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;第三行为一个正整数m,表示交换操作的次数;以下m行每行包含两个正整数ai和bi¬,表示交换位置ai与位置bi的小朋友。
Output
输出文件共m行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度。
Sample Input
【样例输入】
3
130 150 140
2
2 3
1 3
3
130 150 140
2
2 3
1 3
Sample Output
1
0
3
【样例说明】
未进行任何操作时,(2,3)满足条件;
操作1结束后,序列为130 140 150,不存在满足ihj的(i,j)对;
操作2结束后,序列为150 140 130,(1,2),(1,3),(2,3)共3对满足条件的(i,j)。
【数据规模和约定】
对于100%的数据,1≤m≤2*103,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。
0
3
【样例说明】
未进行任何操作时,(2,3)满足条件;
操作1结束后,序列为130 140 150,不存在满足ihj的(i,j)对;
操作2结束后,序列为150 140 130,(1,2),(1,3),(2,3)共3对满足条件的(i,j)。
【数据规模和约定】
对于100%的数据,1≤m≤2*103,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。
HINT
Source
学分块的时候遇到这道题,当时想到了树套树的做法,课后就用树套树水过了,后来发现分块练习题一万个不会写,于是又回头来用分块写了这道题。
夯实基础很重要啊QAQ,不要总想搞个***
思路:
不难得知,杂乱程度即为逆序对个数,那么每次交换(x,y)后逆序对个数的变化只与[x,y]这段区间有关,则问题转化成查询区间内权值在[a,b]的个数。
①树套树可以解决这种问题:
例题:bzoj3110: [Zjoi2013]K大数查询
②分块,对于每个块开一个树状数组。
树套树代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<climits>
#include<queue>
#include<stack>
#include<map>
#define N 200002
#define M 5000002
using namespace std;
int n,m,q[N],ans;
int hash[N],tot,num[M];
int sum[M],root[N],ls[M],rs[M],sz;
void insert(int &k,int l,int r,int w,int f)
{
if(!k)k=++sz;sum[k]+=f;
if(l==r)return;int mid=(l+r)>>1;
if(w<=mid)insert(ls[k],l,mid,w,f);
else insert(rs[k],mid+1,r,w,f);
}
int query(int &k,int l,int r,int a,int b)
{
if(!k)return 0;int mid=(l+r)>>1;
if(a<=l&&b>=r)return sum[k];
if(b<=mid)return query(ls[k],l,mid,a,b);
else if(a>mid)return query(rs[k],mid+1,r,a,b);
else return query(ls[k],l,mid,a,mid)+query(rs[k],mid+1,r,mid+1,b);
}
void ins(int pos,int w,int f)
{
int l=1,r=tot,k=1;
while(l!=r)
{
int mid=(l+r)>>1;
insert(root[k],1,n,pos,f);
if(w<=mid)k=k<<1,r=mid;
else k=k<<1|1,l=mid+1;
}insert(root[k],1,n,pos,f);
}
int ask_bit(int a,int b,int w)
{
int l=1,r=tot,k=1,ret=0;
while(l!=r)
{
int mid=(l+r)>>1;
if(w<=r&&w>mid)
{
ret+=query(root[k<<1],1,n,a,b);
k=k<<1|1,l=mid+1;
}
else
k=k<<1,r=mid;
}return ret;
}
int ask_big(int a,int b,int w)
{
int l=1,r=tot,k=1,ret=0;
while(l!=r)
{
int mid=(l+r)>>1;
if(w>=l&&w<=mid)
{
ret+=query(root[k<<1|1],1,n,a,b);
k=k<<1,r=mid;
}
else k=k<<1|1,l=mid+1;
}return ret;
}
/*
3
13 15 14
2
2 3
1 3
*/
int x[N],y[N],cnt;
void init()
{
for(int i=1;i<=n;i++)
{
scanf("%d",&q[i]);
num[++cnt]=q[i];
}scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x[i],&y[i]);
num[++cnt]=x[i];
num[++cnt]=y[i];
}sort(num+1,num+1+cnt);
num[0]=-(1<<30);
for(int i=1;i<=cnt;i++)
if(num[i]!=num[i-1])
hash[++tot]=num[i];
}
int find(int x)
{
int l=1,r=tot,ret;
while(l<=r)
{
int mid=(l+r)>>1;
if(hash[mid]<=x)
l=mid+1,ret=mid;
else r=mid-1;
}return ret;
}
int main()
{
freopen("in.txt","r",stdin);
freopen("std.txt","w",stdout);
scanf("%d",&n);init();
for(int i=1;i<=n;i++)
{
int ii=find(q[i]);
ans+=ask_big(1,i,ii);
ins(i,ii,1);
}printf("%d\n",ans);
for(int i=1;i<=m;i++)
{
int a=x[i],b=y[i];
if(a>b)swap(a,b);
int ia=find(q[a]),ib=find(q[b]);
ans-=ask_big(a+1,b,ib);
ans+=ask_bit(a+1,b,ib);
ans-=ask_bit(a,b-1,ia);
ans+=ask_big(a,b-1,ia);
if(ia>ib)ans--;
else if(ia<ib)ans++;
ins(a,ia,-1);ins(b,ib,-1);
ins(a,ib,1);ins(b,ia,1);
swap(q[a],q[b]);
printf("%d\n",ans);
}
}
分块代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<climits>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define N 20010
using namespace std;
int read()
{
int x=0,f=1;char ch;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int hash[N],tot,num[N];
int n,m,ans,B,l[N],r[N];
int q[N],C[200][N],bel[N];
int find(int x)
{
int l=1,r=tot,ret;
while(l<=r)
{
int mid=(l+r)>>1;
if(hash[mid]>=x)
r=mid-1,ret=mid;
else l=mid+1;
}return ret;
}
int lowbit(int x){return x&(-x);}
void add(int id,int x,int val)
{while(x<=tot){C[id][x]+=val;x+=lowbit(x);}}
int ask(int id,int x)
{int ret=0;while(x){ret+=C[id][x];x-=lowbit(x);}return ret;}
void solve(int x,int y)
{
int L=min((x-1)/B+2,(n-1)/B+1),R=(y-1)/B;
int s=find(q[x]),t=find(q[y]);
for(int i=L;i<=R;i++)
{
ans+=ask(i,tot)-ask(i,s);
ans-=ask(i,s-1);
ans+=ask(i,t-1);
ans-=ask(i,tot)-ask(i,t);
}int l1=x+1,r1=l[L],l2=r[R]+1,r2=y;
if(L>R)l1=x+1,r1=y;
for(int i=l1;i<r1;i++)
{
if(q[i]>q[x])ans++;
else if(q[i]<q[x])ans--;
if(q[i]>q[y])ans--;
else if(q[i]<q[y])ans++;
}if(L>R)l2=r2+1;
for(int i=l2;i<r2;i++)
{
if(q[i]>q[x])ans++;
else if(q[i]<q[x])ans--;
if(q[i]>q[y])ans--;
else if(q[i]<q[y])ans++;
}
if(q[x]>q[y])ans--;else if(q[x]<q[y])ans++;
int tx=find(q[x]),ty=find(q[y]);
add(bel[x],tx,-1);add(bel[x],ty,1);
add(bel[y],ty,-1);add(bel[y],tx,1);
swap(q[x],q[y]);
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("my.txt","w",stdout);
n=read();B=sqrt(n);int i;
for(i=1;i<=n;i++)
{
q[i]=read();
num[i]=q[i];
}sort(num+1,num+1+n);
for(i=1;i<=n;i++)
if(num[i]!=num[i-1])
hash[++tot]=num[i];
for(i=1;i<=n;i++)
{
bel[i]=(i-1)/B+1;int t=find(q[i]);
ans+=ask(0,tot)-ask(0,t);add(0,t,1);
}printf("%d\n",ans);
for(i=1;i<=(n-1)/B+1;i++)l[i]=0x3f3f3f3f;
for(i=1;i<=n;i++)
{
r[bel[i]]=max(i,r[bel[i]]);
l[bel[i]]=min(l[bel[i]],i);
add(bel[i],find(q[i]),1);
}m=read();
for(i=1;i<=m;i++)
{
int x=read(),y=read();
if(x>y)swap(x,y);
solve(x,y);printf("%d\n",ans);
}
}