2020百度之星初赛三 1003 Permutation 基础小学数学题

Problem Description

一开始有 nnn 个数,他们按 1…n1…n1…n 的顺序排列,要求交换最多 mmm 对数字(同一个数字可以参与多次交换),使得逆序对数目最大。

对于一个序列 AAA,如果存在正整数 i,ji, ji,j 使得 1≤iA[j]A[i] > A[j]A[i]>A[j],则 \lt A[i], A[j] \gt 这个有序对称为 AAA 的一个逆序对。
Input

第一行一个正整数 test (1≤test≤100000)test~(1 \leq test \leq 100000)test (1≤test≤100000) 表示数据组数。

对于每组数据,一行两个整数 n,m (1≤n≤1000000,0≤m≤1000000)n,m~(1 \leq n \leq 1000000, 0 \leq m \leq 1000000)n,m (1≤n≤1000000,0≤m≤1000000) 表示数字个数和最多可以交换的数字对数。
Output

对于每组数据,一行一个整数表示答案。
Sample Input

6
1 1
2 0
2 1
3 1
4 1
4 2

Sample Output

0
0
1
3
5
6

这是一道很简单的题,
思路 : 对于一个长度为n的有序列1,2,3,4,5,...n可以发现

  • 顺序排列逆序对个数为0,如1 2 3 4
  • 逆序排列逆序对个数最多,为 n ∗ ( n − 1 ) 2 \frac{n*(n-1)}{2} 2n(n1)个,如4 3 2 1
  • 第一次交换1n一定能的到最多的逆序对个数(n-1)+(n-2)个逆序对,
  • 第二次交换2n-1一定最优,第三次交换3n-2一定最优
  • …以此类推,最后最多交换 ⌊ n / 2 ⌋ ⌊n/2⌋ n/2次(超出部分忽略)即可得到答案,

例如 : 最后一组样例
开始时 : 1 2 3 4 交换0次 逆序对个数0
m=1时 : 4 2 3 1 交换1次 逆序对增加了(4-1)+(4-2)
m=2时 : 4 3 2 1 交换2次 逆序对增加了(2-1)+(2-2)
m=3时 : 4 3 2 1 交换0次 当前已经是逆序数对最多的排列了,无需交换

观察到1到10m从0增大到n/2服从如下表

	10 : 17  13  9  5  1  
	9 : 15  11  7  3  
	8 : 13  9  5  1  
	7 : 11  7  3  
	6 : 9  5  1  
	5 : 7  3  
	4 : 5  1  
	3 : 3  
	2 : 1  
	1 : 
#define debug
#ifdef debug
#include 
#include "/home/majiao/mb.h"
#endif

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define MAXN ((int)1e5+7)
#define ll long long 
#define int long long
#define INF (0x7f7f7f7f)
#define fori(lef, rig) for(int i=lef; i<=rig; i++)
#define forj(lef, rig) for(int j=lef; j<=rig; j++)
#define fork(lef, rig) for(int k=lef; k<=rig; k++)
#define QAQ (0)

using namespace std;

#ifdef debug
#define show(x...)                                 \
	do {                                           \
		cout << "\033[31;1m " << #x << " -> ";     \
		err(x);                                    \
	} while (0) 
#else
#define show(x...)  
#endif

void err() { cout << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }

namespace FastIO {

	char print_f[105];
	void read() { }
	void print() { putchar('\n'); }

	template <typename T, typename... T2>
		inline void read(T &x, T2 &... oth) {
			x = 0;
			char ch = getchar();
			ll f = 1;
			while (!isdigit(ch)) {
				if (ch == '-') f *= -1; 
				ch = getchar();
			}
			while (isdigit(ch)) {
				x = x * 10 + ch - 48;
				ch = getchar();
			}
			x *= f;
			read(oth...);
		}
	template <typename T>
		inline void put(T x) {
			if(x==0) { putchar('0'); putchar('\n'); return; }
			if(x<0) { putchar('-'); x = -x; }
			int num=0;
			char ch[128];
			while(x) ch[++num] = x % 10 + '0', x /= 10;
			while(num) putchar(ch[num--]);
			putchar('\n');
		}
}; // namespace FastIO
using FastIO::read;
using FastIO::put;

int n, m, Q, K;

/**
	10 : 17  13  9  5  1  
	9 : 15  11  7  3  
	8 : 13  9  5  1  
	7 : 11  7  3  
	6 : 9  5  1  
	5 : 7  3  
	4 : 5  1  
	3 : 3  
	2 : 1  
	1 : 

 */

signed main() {
#ifdef debug
	freopen("test", "r", stdin);
	// freopen("out_main", "w", stdout);
	clock_t stime = clock();
#endif
	read(Q);
	while(Q--) {
		read(n, m);
		if(m == 0 || (n == 1)) {
			printf("0\n");
			continue ;
		}
		int N = n / 2;
		if(m >= N) {
			m = n / 2;
		}
//		m = (m % (n/2) == 0 ? (n/2) : (m%(n/2)));
		int ans = n*2 - 3;
		m --;
		int tmp = ans * m;
		tmp -= (m*4 + (m*(m-1))/2*4);
		ans += tmp ;
//		show(ans, tmp, m);
		printf("%lld\n", ans);
	}
#if 0
	for(n=10; n>=1; n--) {
		printf("%d : ", n);
		for(int i=n; (i-2)>=0; i-=2) {
			printf("%d  ", i*2-3);
		}
		printf("\n");
	}
#endif


















#ifdef debug
	clock_t etime = clock();
	printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif 
	return 0;
}


你可能感兴趣的:(2020百度之星初赛三 1003 Permutation 基础小学数学题)