P1975 [国家集训队]排队
题目
做法
逆序对的题当然想办法用cdq做
交换数列的位置好像不好处理,加个时间轴,把交换操作换成:删、删、加、加(位置可变换)
删的贡献系数为\((-1)\),加的贡献系数为\((1)\),然后丢到树状数组也是根据这个系数,这样可以保证不重复统计同一位置
位置为第一维,时间为第二维,注意排序位置时:\(x_1==x_2\)&&\(y_1<y_2\),因为\(y_1\)放到后面会影响\(x_2\)的
My complete code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<string>
using namespace std;
typedef long long LL;
const LL maxn=1e5;
inline LL Read(){
LL x(0),f(1);char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;c=getchar();
}
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*f;
}
struct node{
LL t,x,y,w,id;
bool operator <(const node &b)const{
return (x<b.x||(x==b.x&&y<b.y));
}
}a[maxn],Kl[maxn];
LL n,m,tot,cnt,num,tim;
LL tmp[maxn],val[maxn],tree[maxn],ans[maxn];
inline LL Lowbit(LL x){
return x&(-x);
}
inline LL Query(LL x){
LL ret(0);
for(;x;x-=Lowbit(x))
ret+=tree[x];
return ret;
}
inline void Add(LL x,LL c){
for(;x<=tot;x+=Lowbit(x))
tree[x]+=c;
}
void Cdq(LL l,LL r){
if(l==r)
return;
LL mid(l+r>>1);
for(LL i=l;i<=r;++i)
if(a[i].t<=mid)
Add(a[i].y,a[i].w);
else
ans[a[i].id]+=a[i].w*(Query(tot)-Query(a[i].y));
for(LL i=l;i<=r;++i)
if(a[i].t<=mid)
Add(a[i].y,-a[i].w);
for(LL i=r;i>=l;--i)
if(a[i].t<=mid)
Add(a[i].y,a[i].w);
else
ans[a[i].id]+=a[i].w*(Query(a[i].y-1));
for(LL i=l;i<=r;++i)
if(a[i].t<=mid)
Add(a[i].y,-a[i].w);
LL t1(l-1),t2(mid);
for(LL i=l;i<=r;++i)
if(a[i].t<=mid)
Kl[++t1]=a[i];
else
Kl[++t2]=a[i];
for(LL i=l;i<=r;++i)
a[i]=Kl[i];
Cdq(l,mid),Cdq(mid+1,r);
}
int main(){
n=Read();
for(LL i=1;i<=n;++i)
tmp[i]=val[i]=Read();
sort(tmp+1,tmp+1+n); tot=unique(tmp+1,tmp+1+n)-tmp-1;
for(LL i=1;i<=n;++i)
val[i]=lower_bound(tmp+1,tmp+1+tot,val[i])-tmp;
for(LL i=1;i<=n;++i)
a[++num]=(node){++tim,i,val[i],1,0};
m=Read();
for(LL i=1;i<=m;++i){
LL x(Read()),y(Read());
a[++num]=(node){++tim,y,val[x],1,i},
a[++num]=(node){++tim,x,val[y],1,i},
a[++num]=(node){++tim,x,val[x],-1,i},
a[++num]=(node){++tim,y,val[y],-1,i};
swap(val[x],val[y]);
}
sort(a+1,a+1+num);
Cdq(1,num);
printf("%lld\n",ans[0]);
for(LL i=1;i<=m;++i){
ans[i]+=ans[i-1],
printf("%lld\n",ans[i]);
}
return 0;
}/*
3
130 150 140
2
2 3
1 3
*/