P1975 [国家集训队]排队

题目

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
*/
posted @ 2019-01-19 20:13  y2823774827y  阅读(185)  评论(0编辑  收藏  举报