ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2020-10-05 08:33:07  阅读:213  来源: 互联网

标签:NOI int Online 冒泡排序 ans 对数 include 逆序


题目

sol:

考虑一下冒泡排序的过程,从左侧开始,将第一个数\(x_1\)拿到第一个比它的的位置,同时将这个比它大的数\(x_2\)拿到下一个比x_2的的位置,这样一直循环下去。

假设有一次操作,我们将x[i]拿到比它大的位置j上去,那么(i, j)这个区间中的数相当于往前移动的一位,并且逆序对数会减少1。并且我们发现,x[i]的逆序对数一定是0,因为如果不是0,
那么它就不可能被拿出来。 那么我们可以得到一个结论,经过一轮冒泡排序,第i个位置上的数的逆序对数变为 :

\[c_i = max(c_{i + 1} - 1, 0) \]

经过k轮冒泡排序,那么答案为:

\[ans = \sum_{i >=k + 1} (c_i - k) \]

可以用两个权值树状数组来维护。

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int N = 2e5 + 100;
typedef long long LL;

LL tr[N], T[N], c[N], ans;
int n, q, a[N];

inline int lowbit(int x) {
	return x & -x; 
} 

void add(int x, int v) {
	for(; x <= n + 3; x += lowbit(x))
		tr[x] += v;
}
LL ask(int x) {
	LL res = 0;
	for(; x; x -= lowbit(x))
		res += tr[x];
	return res;
}
void change(int x, int v) {
	for(; x <= n + 3; x += lowbit(x))
		T[x] += v;
}
LL query(int x) {
	LL res = 0;
	for(; x; x -= lowbit(x))
		res += T[x];
	return res;
}

void output(LL* s) {
	puts("Debug");
	for(int i = 1; i <= n; i ++)
	    printf("%lld ", s[i]);
	puts(""); 
}

int main()
{
//#ifdef LOCAL
//	freopen("E:\\data.in.txt", "r", stdin);
//#endif
	scanf("%d%d", &n, &q);
	for(int i = 1; i <= n; i ++) {
		scanf("%d", &a[i]);
		c[i] = ask(n) - ask(a[i]); 
		add(a[i], 1);
		if( c[i])  change(c[i], c[i]);
	}
	for(int i = 1; i <= n; i ++)    add(i, -1);
	for(int i = 1; i <= n; i ++)    
	    if(c[i])  add(c[i], 1);//下标不能为0 
	
	while(q --) {
		int op, x;
		scanf("%d%d", &op, &x);
		if( op == 1) {
			if(c[x])    
			    change(c[x], -c[x]),  add(c[x], -1);
			if(c[x + 1])
			    change(c[x + 1], -c[x + 1]), add(c[x + 1], -1);
			swap(c[x], c[x + 1]);
			if( a[x] < a[x + 1]) {
				c[x + 1] ++;
				change(c[x + 1], c[x + 1]);
				add(c[x + 1], 1);
				if(c[x])    
			        change(c[x], c[x]),  add(c[x], 1);
			} else {
				c[x] --;
				if(c[x])    
				    change(c[x], c[x]), add(c[x], 1);
				if(c[x + 1])
			        change(c[x + 1], c[x + 1]), add(c[x + 1], 1);
			}
			
			swap(a[x], a[x + 1]);
		} else {
			if(x >= n)	{
				puts("0");
				continue;
			}
			ans = query(n + 1) - query(x);
			ans -= x * (ask(n + 1) - ask(x)); 
			printf("%lld\n", ans);
		}
	}
	return 0;
} 
/*
3 6
2 1 3
2 0

*/

标签:NOI,int,Online,冒泡排序,ans,对数,include,逆序
来源: https://www.cnblogs.com/wyy0804/p/13769277.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有