[NOI Online #1 提高组]冒泡排序

这个题很绕,记数字i前面有cns[i]个数字比他大,逆序对个数就是sigmi cns[i]

反转k次就是让cns[i] - k (i>=1 && i <= n) 而且cns[i]不能有负数

 

利用两个线段树维护一下,就是有点绕。。。。

 

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll ;

const int maxn = 2e5+11;
struct Node{	
	ll ans,sum;
}tree[4][maxn*4];

int update(int id,int node,int be,int en,int i,int val){
	int mid = be + en >> 1;
	int l = node*2;
	int r = node*2+1;
	if(be == en){
		tree[id][node].ans += val;
		
		if(val > 0) tree[id][node].sum += 1;
		if(val < 0) tree[id][node].sum -= 1; 
		return 0;
	}
	if(i <= mid) update(id,l,be,mid,i,val);
	else update(id,r,mid+1,en,i,val);
	tree[id][node].ans = tree[id][l].ans + tree[id][r].ans;
	tree[id][node].sum = tree[id][l].sum + tree[id][r].sum;
	return 0;
}


ll ask(int id,int node,int be,int en,int LL,int RR){
	int mid = be + en >> 1;
	int l = node*2;
	int r = node*2+1;
	if(LL <= be && en <= RR){
		return tree[id][node].ans;
	}
	ll a = 0;
	if(LL <= mid) a += ask(id,l,be,mid,LL,RR);
	if(RR >  mid) a += ask(id,r,mid+1,en,LL,RR);
	return a;
}

ll ask2(int id,int node,int be,int en,int LL,int RR){
	int mid = be + en >> 1;
	int l = node*2;
	int r = node*2+1;
	if(LL <= be && en <= RR){
		return tree[id][node].sum;
	}
	ll a = 0;
	if(LL <= mid) a += ask2(id,l,be,mid,LL,RR);
	if(RR >  mid) a += ask2(id,r,mid+1,en,LL,RR);
	return a;
}

int list[maxn];
ll cns[maxn];

int main(){
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&list[i]);
		ll a = 0;
		if(list[i] != n) a = ask(0,1,1,n,list[i]+1,n);
		cns[list[i]] = a;
		update(2,1,1,n,list[i],a);
		
		if(a != 0) update(1,1,1,n,a,a);
		
		update(0,1,1,n,list[i],1); 
	}
	
	while(m--){
		int x,y;
		scanf("%d%d",&x,&y);
		if(x == 1){
			if(list[y] < list[y+1]){
				ll ans = cns[list[y]];
				if(ans != 0) update(1,1,1,n,ans,-ans);
				update(1,1,1,n,ans+1,ans+1);
				
				cns[list[y]]++;
				update(2,1,1,n,list[y],1);
			}
			else{
				ll ans = cns[list[y+1]];
				update(1,1,1,n,ans,-ans);
				if(ans - 1 != 0) update(1,1,1,n,ans-1,ans-1);
				
				cns[list[y+1]]--;
				update(2,1,1,n,list[y+1],-1);
			}
			swap(list[y],list[y+1]);
		}
		else{
			ll ans = 0;
			if(y == 0){
				ans = ask(2,1,1,n,1,n);
			}
			else if(y >= n){
				ans = 0;
			}
			else{
				ans = ask(2,1,1,n,1,n) - ask(1,1,1,n,1,y) - ask2(1,1,1,n,y+1,n)*y;
//				cout<<ask(2,1,1,n,1,n)<<" "<<ask(1,1,1,n,1,y)<<" "<<ask2(1,1,1,n,y+1,n)<<endl;
			}
			
			printf("%lld\n",ans);
		}
	}
	
	
	
	
	return 0;
}

  

上一篇:Self-Supervised Learning with Swin Transformers


下一篇:Online Learning算法理论与实践