BZOJ2141: 排隊

BZOJ2141: 排隊php

Description

排排坐,吃果果,生果甜嗦嗦,你們笑呵呵。你一個,我一個,大的分給你,小的留給我,吃完果果唱支歌,你們樂和和。
紅星幼兒園的小朋友們排起了長長地隊伍,準備吃果果。不過由於小朋友們的身高有所區別,排成的隊伍高低錯亂,極不美觀。
設第i個小朋友的身高爲hi,咱們定義一個序列的雜亂程度爲:知足ihj的(i,j)數量。
幼兒園阿姨每次會選出兩個小朋友,交換他們的位置,請你幫忙計算出每次交換後,序列的雜亂程度。
爲方便幼兒園阿姨統計,在未進行任何交換操做時,你也應該輸出該序列的雜亂程度。

Input

第一行爲一個正整數n,表示小朋友的數量;
第二行包含n個由空格分隔的正整數h1,h2,…,hn,依次表示初始隊列中小朋友的身高;
第三行爲一個正整數m,表示交換操做的次數;
如下m行每行包含兩個正整數ai和bi,表示交換位置ai與位置bi的小朋友。
1≤m≤2*10^3,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。

Output

輸出文件共m行,第i行一個正整數表示交換操做i結束後,序列的雜亂程度。html

Sample Input

【樣例輸入】
3
130 150 140
2
2 3
1 3

Sample Output

1
0
3
【樣例說明】
未進行任何操做時,(2,3)知足條件;
操做1結束後,序列爲130 140 150,不存在知足i<j且hi>hj的(i,j)對;
操做2結束後,序列爲150 140 130,(1,2),(1,3),(2,3)共3對知足條件的(i,j)

題解Here!

其實有一道極其類似的題:

BZOJ4889: [TJOI2017]不勤勞的圖書管理員

可是這題相對簡單,只要求逆序對個數便可。ios

因此直接樹狀數組+主席樹。數組

假設咱們交換的是$x,y$,咱們發現:ide

$[1,x-1],[y+1,n]$的答案是不變的;post

$[x+1,y-1]$的答案會發生小幅度變化;ui

$x,y$的答案要從新算。url

因此,咱們只要管$[x+1,y-1]$中數字對$x,y$的影響便可。spa

具體過程不難思考。htm

時空複雜度均爲$O(n\log_2^2n)$。

一開始我把主席樹的空間開小了$(50W)$硬生生$RE\times 2$,一怒之下直接開$800W$怒$A$此題。。。

附代碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 20010
using namespace std;
int n,m,num,ans=0;
int val[MAXN],lsh[MAXN],root[MAXN];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
namespace CT{
	int size=0;
	struct Chairman_Tree{
		int sum,lson,rson;
	}a[MAXN*400];
	void insert(int k,int v,int l,int r,int &rt){
		a[++size]=a[rt];rt=size;
		a[rt].sum+=v;
		if(l==r)return;
		int mid=l+r>>1;
		if(k<=mid)insert(k,v,l,mid,a[rt].lson);
		else insert(k,v,mid+1,r,a[rt].rson);
	}
	int sum(int lside,int rside,int l,int r,int rt){
		if(lside<=l&&r<=rside)return a[rt].sum;
		int mid=l+r>>1,ans=0;
		if(lside<=mid)ans+=sum(lside,rside,l,mid,a[rt].lson);
		if(mid<rside)ans+=sum(lside,rside,mid+1,r,a[rt].rson);
		return ans;
	}
	inline int lowbit(int x){return x&(-x);}
	void update(int x,int k,int v){for(;x<=n;x+=lowbit(x))insert(k,v,1,num,root[x]);}
	int query(int l,int r,int lside,int rside){
		int s=0;
		for(;r;r-=lowbit(r))s+=sum(lside,rside,1,num,root[r]);
		for(--l;l;l-=lowbit(l))s-=sum(lside,rside,1,num,root[l]);
		return s;
	}
}
void work(){
	int x,y;
	while(m--){
		x=read();y=read();
		if(x>y)swap(x,y);
		
		if(val[x]>1)ans-=CT::query(x+1,y,1,val[x]-1);
		if(val[y]<num)ans-=CT::query(x,y-1,val[y]+1,num);
		if(val[x]>val[y])ans++;
		
		CT::update(x,val[x],-1);
		CT::update(y,val[y],-1);
		swap(val[x],val[y]);
		CT::update(x,val[x],1);
		CT::update(y,val[y],1);
		
		if(val[x]>1)ans+=CT::query(x+1,y,1,val[x]-1);
		if(val[y]<num)ans+=CT::query(x,y-1,val[y]+1,num);
		if(val[x]>val[y])ans--;
		
		printf("%d\n",ans);
	}
}
void init(){
	n=read();
	for(int i=1;i<=n;i++)val[i]=lsh[i]=read();
	m=read();
	sort(lsh+1,lsh+n+1);
	num=unique(lsh+1,lsh+n+1)-lsh-1;
	for(int i=1;i<=n;i++){
		val[i]=lower_bound(lsh+1,lsh+num+1,val[i])-lsh;
		CT::update(i,val[i],1);
		if(val[i]<num)ans+=CT::query(1,i,val[i]+1,num);
	}
	printf("%d\n",ans);
}
int main(){
	init();
	work();
	return 0;
}
相關文章
相關標籤/搜索