2022-03-09每日刷题打卡

2022-03-09每日刷题打卡

力扣——每日一题

798. 得分最高的最小轮调

给你一个数组 nums,我们可以将它按一个非负整数 k 进行轮调,这样可以使数组变为 [nums[k], nums[k + 1], … nums[nums.length - 1], nums[0], nums[1], …, nums[k-1]] 的形式。此后,任何值小于或等于其索引的项都可以记作一分。

例如,数组为 nums = [2,4,1,3,0],我们按 k = 2 进行轮调后,它将变成 [1,3,0,2,4]。这将记为 3 分,因为 1 > 0 [不计分]、3 > 1 [不计分]、0 <= 2 [计 1 分]、2 <= 3 [计 1 分],4 <= 4 [计 1 分]。
在所有可能的轮调中,返回我们所能得到的最高分数对应的轮调下标 k 。如果有多个答案,返回满足条件的最小的下标 k 。

示例 1:

输入:nums = [2,3,1,4,0]
输出:3
解释:
下面列出了每个 k 的得分:
k = 0, nums = [2,3,1,4,0], score 2
k = 1, nums = [3,1,4,0,2], score 3
k = 2, nums = [1,4,0,2,3], score 3
k = 3, nums = [4,0,2,3,1], score 4
k = 4, nums = [0,2,3,1,4], score 3
所以我们应当选择 k = 3,得分最高。

题目是说当下标i大于等于nums[i]时,算一分,问我们移动几轮可以时获得的分最大。我们需要考虑一下,什么时候移动会使得分数发生改变:当一个数的下标正好等于这个元素的值时,此时如果移动,移动后的下标就会小于元素的值,分数会从1变成0;如果是下标大于这个元素的,移动后依然大于元素的值,分数不变仍是1分;如果是下标小于元素的,移动后依然小于,仍是0分;还有就是位于数组开头的,移动后会移动到末尾去,那么必然会算上一分(数组的值是:0~数组长度,所以只要在末尾,那下标必大于或等于元素),这么下来只有下标等于元素的地方比较特殊。那么,我们只要算出移动k次后,元素等于下标的个数,就可以知道下一次分数的变化了,比如说,

2 1 4 3 0这个数组,此时分数是2,元素等于下标的只有一个(元素3),此时移动一格,元素等于下标的一个都没有了,那么分数就要-之前元素等于下标的个数,即2-1=1,同时因为2移动到了末尾,分数必加1,所以分数就是1+1=2。由此可见,只要我们知道移动k次后

元素等于下标的个数即可。我们准备一个数组v,意思是当移动i次后,有v[i]个元素等于下标,在准备一个数res=0,用来记录初始的分数。遍历nums,每个元素到达对应的下标所要移动的次数是(数组长度-nums[i]+i),首先不管你在哪个位置,向前移动i次后必然在起点,然后向后移动nums[i]次不就是元素等于下标了。还有就是,如果nums[i]<=i,那移动的次数也可以是(数组长度-nums[i]+i)不过还要%数组长度,为了方便也可以是(nums[i]+i),同时res要++,因为元素小于等于下标要记一分。

然后遍历v数组,看移动k次后的分数,移动k次后的分数就是res-v[i-1]+1,v[i-1]是移动前元素等于下标的个数,res是分数,因为移动了,所以之前等于下标的那些元素都变成了大于下标,所以分数要扣掉,同时因为第一个元素移动到了末尾,分数要+1,所以分数计算是res-v[i]+1,在遍历v数组中维护最大值,同时记录最大值出现的k是多少。最后把记录下来的k返回。

class Solution {
public:
    int bestRotation(vector<int>& nums) {
        int n=nums.size();
        vector<int>v(n);
        int res=0;
        for(int i=0;i<n;i++)
        {
            if(nums[i]>i)
            {
                v[n+i-nums[i]]++;
            }
            else
            {
                v[i-nums[i]]++;
                res++;
            }
        }
        int max_sc=res,k=0;
        for(int i=1;i<n;i++)
        {
            res=res-v[i-1]+1;
            if(res>max_sc)
            {
                max_sc=res;
                k=i;
            }
        }
        return k;
    }
};
2193. 得到回文串的最少操作次数

给你一个只包含小写英文字母的字符串 s 。

每一次 操作 ,你可以选择 s 中两个 相邻 的字符,并将它们交换。

请你返回将 s 变成回文串的 最少操作次数 。

注意 ,输入数据会确保 s 一定能变成一个回文串。

示例 1:

输入:s = “aabb”
输出:2
解释:
我们可以将 s 变成 2 个回文串,“abba” 和 “baab” 。

  • 我们可以通过 2 次操作得到 “abba” :“aabb” -> “abab” -> “abba” 。
  • 我们可以通过 2 次操作得到 “baab” :“aabb” -> “abab” -> “baab” 。
    因此,得到回文串的最少总操作次数为 2 。

提示:

  • 1 <= s.length <= 2000
  • s 只包含小写英文字母。
  • s 可以通过有限次操作得到一个回文串。

虽然是困难,但最长才2000哎,这不暴力贪他一手。

开始前我们要知道一个事,一个字符在字符串里两两交换移动位置,那么除了那个字符以外的字符,他们的相对顺序是不变的,比如字符串aabcc,我们把第二个a一到最右边,那么最后就算abcca,可以发现,确实除了我们交换的c其它字符的相对位置不发生变化,这也说明了交换后不会对其它的字符产生影响。

双指针+贪心。我们的想法是,对一个字符串我们从两边开始找,固定一段,另外一段向着这一段移动,比如aabbc,我们这里固定的是左端,那么我们就从右边开始,找第一个等于左端字符的,即下标为1的另一个a,然后我们通过交换把a移动到最右边使其变成abbca,这样两边就算回文了,我们忽略这两边的字符,这样我们眼里就只有bbc了,继续如上操作。如果找到的字符是单个的,那我们就假设把它移动到中间,比如caabb,我们计算把它移动到中间的次数,但并不真正的交换它,因为如果把c移到中间,那我们就要把它去掉,但这是比较麻烦的,而且也不能像两边一样忽视它,这样使得我们在移动一些字符时会经过它,这样会使得我们的交换次数+1,比如c移到中间后是aacbb,此时我们把a移到末尾,次数是3,但如果去掉它,字符串就是aabb,我们把a移到末尾就只用2次了,而就像前面说的,把一个字符从中间删掉并不容易,而且移到中间后也不能无视它,那么我们就假设它被移到中间就行,实际并不理他,下一次循环我们就直接跳过这个元素即可。

int minMovesToMakePalindrome(string s) {
        int res=0,n=s.size(),l=0,r=n-1;
        while(l<r)
        {
            int k=r;
            for(;k!=l;k--)
                if(s[l]==s[k])break;
            if(k==l)
            {
                res+=n/2-l;
            }
            else
            {
                for(int i=k;i<r;i++)
                {
                    swap(s[i],s[i+1]);
                    res++;
                }
                r--;
            }
            l++;
        }
        return res;
    }

代码源——div2每日一题

跳跳 - 题目 - Daimayuan Online Judge

平面上给定了一些整点(横纵坐标均为整数的点),被称为 “魔法阵”。魔法少女派派想要在各魔法阵之间传送,每一次传送,她将使用下面的方式:

  1. 刚开始,派派已经位于某传送阵之上;
  2. 如果派派掌握一种魔法 (A,B),其中 A,BA,B 均为整数。使用一次这个魔法可以让派派从任意整点 (X,Y) 瞬间移动至 (X+A,Y+B);
  3. 选择一种魔法并开始传送,在一次传送过程中可以使用多次该魔法,但在抵达下一个传送阵之前仅能使用这一种魔法

问派派至少需要掌握多少种魔法,才能在从任意魔法阵直接传送到任意魔法阵?

输入格式

第一行一个整数 N。

接下来一行 N 行,每行包含两个整数 Xi,Yi, 表示每个魔法阵的坐标。

输出格式

一个数,表示答案。

样例1输入
3
1 1
4 5
1 4
样例1输出
6

解释: 任务是从 (1,1) 传送至 (4,5) 以及 (1,4) 、从(4,5) 传送至 (1,1) 以及(1,4) 、从 (1,4) 传送至 (1,1) 以及 (4,5) 。

注意你不能使用 (0,3)+(3,1) 的魔法从 (1,1) 到达(4,5)。因为每次移动,你只能使用一种魔法。

当然,你可以学习 (0,1),那样的话,从 (1,1) 到达 (1,4) 则需要使用 3 次 (0,1) 魔法了。

样例2输入
3
1 1
2 2
1000000000 1000000000
样例2输出
2
数据规模
  • N∈[10,500]
  • Xi,Yi∈[0,10^9], 但保证坐标之间两两不同

太让人感动了这个数据量,直接暴力就可以。

这题最大的难点在解释的时候也说给你了,每次移动只能使用一种魔法,但可以重复使用,这样我们就知道了,我们的魔法阵不是简单的两点之间的差值,而是差值的最简式,即比例不变的情况下,魔法阵的两边值最小。比如样例2输入里的(1,1),(2,2),(1000000000,1000000000)正常情况魔法阵应该有(1,1)(-1,-1)(99999999,99999999)(-99999999,-99999999)(99999998,99999998)和(-99999998,-99999998)这6个,但他们可以化成最简式,化简后就只有两种情况了(1,1)和(-1,-1),这样我们从(1,1)到(1000000000,1000000000)只要使用99999999次(1,1)魔法阵即可。

至于化简魔法阵两边的值,我们可以用他们除去最大公约数的绝对值,这样得到的就是两边的最简式了(注意是绝对值,不然如果法阵是负数,这样公约数也是负数,两者相除得到的就算正数了,这显然是不对的),每有一个魔法阵,就用map记录下来,防止有重复的。但有一点特殊情况,即(0,y)和(x,0)的情况,此时他们没有最大公约数,但就像解释里说的,我们之间把他们化成(0,1)和(1,0)的情况即可。最后输出法阵的个数。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>

typedef long long ll;
typedef pair<ll, ll>PII; 
const int MOD = 1e9 + 7;
const int N = 200010;
ll f[N+50][10];

int gcd(int x, int y)
{
	while (y ^= x ^= y ^= x %= y);
	return x;
}

int main()
{
	ll n, x, y;
	vector<PII>v;
	cin >> n;
	map<PII, int>mymap;
	for (int i = 0; i < n; i++)
	{
		cin >> x >> y;
		v.push_back({ x,y });
	}
	ll res = 0;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			if (j == i)continue;
			int x = v[j].first - v[i].first;
			int y = v[j].second - v[i].second;
			if (x == 0 || y == 0)
			{
				x = x != 0 ? x / abs(x) : x;
				y = y != 0 ? y / abs(y) : y;
			}
			else
			{
				int num = abs(gcd(x, y));
				x /= num;
				y /= num;
			}
			if (mymap[{x, y}] == 0)
			{
				mymap[{x, y}] = 1;
				res++;
			}
		}
	}
	cout << res << endl;
	return 0;
}

CodeForces

Problem - A - Codeforces

The string s is given, the string length is odd number. The string consists of lowercase letters of the Latin alphabet.

As long as the string length is greater than 1, the following operation can be performed on it: select any two adjacent letters in the string s and delete them from the string. For example, from the string “lemma” in one operation, you can get any of the four strings: “mma”, “lma”, “lea” or “lem” In particular, in one operation, the length of the string reduces by 2.

Formally, let the string ss have the form s=s1s2…sn (n>1). During one operation, you choose an arbitrary index ii (1≤i<n) and replace s=s1s2…si−1si+2…sn.

For the given string ss and the letter cc, determine whether it is possible to make such a sequence of operations that in the end the equality s=cwill be true? In other words, is there such a sequence of operations that the process will end with a string of length 11, which consists of the letter c?

Input

The first line of input data contains an integer tt (1≤t≤10^3) — the number of input test cases.

The descriptions of the tt cases follow. Each test case is represented by two lines:

  • string s, which has an odd length from 11 to 49 inclusive and consists of lowercase letters of the Latin alphabet;
  • is a string containing one letter c, where cc is a lowercase letter of the Latin alphabet.

Output

For each test case in a separate line output:

  • YES, if the string s can be converted so that s=c is true;
  • NO otherwise.

You can output YES and NO in any case (for example, the strings yEs, yes, Yes and YES will be recognized as a positive response).

Example

input

Copy

5
abcde
c
abcde
b
x
y
aaaaaaaaaaaaaaa
a
contest
t

output

Copy

YES
NO
NO
YES
YES

Note

In the first test case, s=“abcde”. You need to get s=“c”. For the first operation, delete the first two letters, we get s=“cde”. In the second operation, we delete the last two letters, so we get the expected value of s=“c”.

In the third test case, s=“x”, it is required to get s=“y”. Obviously, this cannot be done.

一开始有点看不明白题,后面知道了,意思就是给你一个奇数长度的字符串s和一个字符c,然后让你每次删两个相邻的字母,问你有没有办法把s删的只剩最后一个字符,这个字符等于c。

既然只能删偶数的字母,那就直接遍历s,只要发现字符c,且下标是偶数(下标从0开始,如果你下标是偶数,就说明前面的字符个数也是偶数),那就输出yes。如果一直找不到就输出no。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>
 
typedef long long ll;
typedef pair<int, int>PII; 
const int MOD = 1e9 + 7;
const int N = 200010;
ll f[N+50][10];
 
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		string str;
		char c;
		cin >> str >> c;
		int n = str.size();
		bool flag = true;
		for (int i = 0; i < n; i++)
		{
			if (str[i] == c && i % 2 == 0)
			{
				cout << "YES" << endl;
				flag = false;
				break;
			}
		}
		if (flag)cout << "NO" << endl;
	}
	return 0;
}
Problem - B - Codeforces

Not so long ago, Vlad came up with an interesting function:

  • fa(x)=⌊x/a⌋+x mod a, where ⌊x/a⌋ is x/a, rounded down, x mod a — the remainder of the integer division of x by a.

For example, with a=3 and x=11, the value f3(11)=⌊11/3⌋+11mod3=3+2=5.

The number a is fixed and known to Vlad. Help Vlad find the maximum value of fa(x)fa(x) if xx can take any integer value from ll to r inclusive (l≤x≤r).

Input

The first line of input data contains an integer tt (1≤t≤1041≤t≤104) — the number of input test cases.

This is followed by t lines, each of which contains three integers li, ri and ai (1≤li≤ri≤109,1≤ai≤109) — the left and right boundaries of the segment and the fixed value of a.

Output

For each test case, output one number on a separate line — the maximum value of the function on a given segment for a given a.

Example

input

Copy

5
1 4 3
5 8 4
6 10 6
1 1000000000 1000000000
10 12 8

output

Copy

2
4
5
999999999
5

Note

In the first sample:

  • f3(1)=⌊1/3⌋+1mod3=0+1=1
  • f3(2)=⌊2/3⌋+2mod3=0+2=2
  • f3(3)=⌊3/3⌋+3mod3=1+0=1
  • f3(4)=⌊4/3⌋+4mod3=1+1=2f

As an answer, obviously, f3(2) and f3(4) are suitable.

这题意思是说,给你一个区间l~r和一个数a,让你从区间里找一个数x,使得x/a+x%a的值最大。这道题暴力思路就算是遍历区间,然后枚举x,求结果最大值,但这题的区间范围到了10^9,妥妥超时。但其实,这题是一道数学题,我们分情况讨论,

当区间里的数都小于a时,x/a就只能是0了,那么我们要求的最大值只能从x%a里找,因为x都是小于a的,x越大,x%a就越大,所以当区间里的数都小于a时,我们直接输出右端点。

当右区间大于a时,x/a和x%a都有值,但这并不妨碍我们重复之前的操作,只是在x%a的情况下加上了x/a的值,也就是说,x%a部分的值我们仍然是从0~ a-1的部分中去最大的那个a-1,至于前面的x/a,就看区间最大的值有几个a,我们计算r/a的值,记作ans,x的值就该是ans*a-1,这样函数的最大值就是(ans-1)+a-1了。但有个特殊的地方,比如区间1~19,a是10,这样ans是1,x就是9,计算得到的最大值应该是9,但我们知道最大值应该是10,x应该取19,所以为了应对特殊的情况,计算ans时应该是(r+1)/a。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>
 
typedef long long ll;
typedef pair<int, int>PII; 
const int MOD = 1e9 + 7;
const int N = 200010;
ll f[N+50][10];
 
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		ll l, r, a;
		cin >> l >> r >> a;
		if (r < a)
		{
			cout << r << endl;
		}
		else if (r >= a)
		{
			ll ans = (r + 1) / a;
			ll x = (ans) * a - 1;
			if (l > x)
			{
				x = r;
			}
			cout << x / a + x % a << endl;
		}
		
	}
	return 0;
}
Problem - C - Codeforces

On the number line there are mm points, ii-th of which has integer coordinate xi and integer weight wi. The coordinates of all points are different, and the points are numbered from 1 to m.

A sequence of nn segments [l1,r1],[l2,r2],…,[ln,rn] is called system of nested segments if for each pair i,j (1≤i<j≤n) the condition li<lj<rj<ri is satisfied. In other words, the second segment is strictly inside the first one, the third segment is strictly inside the second one, and so on.

For a given number nn, find a system of nested segments such that:

  • both ends of each segment are one of mm given points;
  • the sum of the weights 2⋅n2⋅n of the points used as ends of the segments is minimal.

For example, let m=8m=8. The given points are marked in the picture, their weights are marked in red, their coordinates are marked in blue. Make a system of three nested segments:

  • weight of the first segment: 1+1=2
  • weight of the second segment: 10+(−1)=9
  • weight of the third segment: 3+(−2)=1
  • sum of the weights of all the segments in the system: 2+9+1=12

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XnDxe8Ag-1646827671245)(https://espresso.codeforces.com/cda411c8d1a8e275a60e641e41a418d9668aa68c.png)]System of three nested segments

Input

The first line of input data contains an integer t (1≤t≤10^4) —the number of input test cases.

An empty line is written before each test case.

The first line of each test case contains two positive integers nn (1≤n≤10^5) and mm (2⋅n≤m≤2⋅10^5).

The next mm lines contain pairs of integers xixi (−109≤xi≤109) and wiwi (−104≤wi≤104) — coordinate and weight of point number ii (1≤i≤m) respectively. All xi are different.

It is guaranteed that the sum of mm values over all test cases does not exceed 2⋅10^5.

Output

For each test case, output n+1 lines: in the first of them, output the weight of the composed system, and in the next nn lines output exactly two numbers — the indices of the points which are the endpoints of the ii-th segment (1≤i≤n1≤i≤n). The order in which you output the endpoints of a segment is not important — you can output the index of the left endpoint first and then the number of the right endpoint, or the other way around.

If there are several ways to make a system of nested segments with minimal weight, output any of them.

Example

input

3

3 8
0 10
-2 1
4 10
11 20
7 -1
9 1
2 3
5 -2

3 6
-1 2
1 3
3 -1
2 4
4 0
8 2

2 5
5 -1
3 -2
1 0
-2 0
-5 -3

output

12
2 6
5 1
7 8

10
1 6
5 2
3 4

-6
5 1
4 2

Note

The first test case coincides with the example from the condition. It can be shown that the weight of the composed system is minimal.

The second test case has only 6 points, so you need to use each of them to compose 3 segments.

这题是说,给你一一个n和m个点,每个点有一个坐标和权重,你现在要把这些点按他们的坐标排序好,然后练成n个线段,线段成涟漪状(大的包住小的)每个线段的权是两个端点的权重之和,问你这n个线段的权和最小是多少,并且从外到内输出这些线段的端点的下标(不是坐标,是输入时的下标,从1开始计数)。

既然他要的是权重合起来最小,那就用贪心的想法,我们准备一个m*3的数组来存点,每个小数组数组代表一个点,记录着那个点的输入时的下标,坐标和权重,我们直接根据权重升序排序,因为只要n个线段,即只要n个点,我们可以把之后的点都删掉。再根据点的坐标继续排序,然后开始输出,先输出这些点权重的sum,再头尾同时输出点的下标。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>

typedef long long ll;
typedef pair<ll, ll>PII;
const int MOD = 1e9 + 7;
const int N = 200010;

bool cmp(vector<ll> a, vector<ll> b)
{
	return a[2] < b[2];
}

bool cmp2(vector<ll> a, vector<ll> b)
{
	return a[1] < b[1];
}

int main()
{
	int m;
	cin >> m;
	while (m--)
	{
		int n, len;
		cin >> n >> len;
		vector<vector<ll>>v(len, vector<ll>(3));
		for (int i = 0; i < len; i++)
		{
			cin >> v[i][1] >> v[i][2];
			v[i][0] = i;
		}
		sort(v.begin(), v.end(),cmp);
		v.erase(v.begin() + 2 * n, v.end());
		sort(v.begin(), v.end(), cmp2);
		ll sum = 0;
		for (auto i : v)sum += i[2];
		cout << sum << endl;
		int l = 0, r = v.size();
		while (l < r-1)
		{
			cout << v[l][0]+1 << " " << v[r-1][0]+1 << endl;
			l++, r--;
		}
	}
	return 0;
}
Problem - D - Codeforces

Petya got an array aa of numbers from 1 to nn, where a[i]=i.

He performed n operations sequentially. In the end, he received a new state of the a array.

At the ii-th operation, Petya chose the first i elements of the array and cyclically shifted them to the right an arbitrary number of times (elements with indexes i+1 and more remain in their places). One cyclic shift to the right is such a transformation that the array a=[a1,a2,…,an]becomes equal to the array a=[ai,a1,a2,…,ai−2,ai−1,ai+1,ai+2,…,an].

For example, if a=[5,4,2,1,3] and i=3 (that is, this is the third operation), then as a result of this operation, he could get any of these three arrays:

  • a=[5,4,2,1,3] (makes 00 cyclic shifts, or any number that is divisible by 3);
  • a=[2,5,4,1,3] (makes 1 cyclic shift, or any number that has a remainder of 1 when divided by 3);
  • a=[4,2,5,1,3] (makes 2 cyclic shifts, or any number that has a remainder of 2 when divided by 3).

Let’s look at an example. Let n=6, i.e. initially a=[1,2,3,4,5,6] A possible scenario is described below.

  • i=1: no matter how many cyclic shifts Petya makes, the array aa does not change.
  • i=2: let’s say Petya decided to make a 1 cyclic shift, then the array will look like a=[2,1,3,4,5,6].
  • i=3: let’s say Petya decided to make 1 cyclic shift, then the array will look like a=[3,2,1,4,5,6].
  • i=4: let’s say Petya decided to make 2 cyclic shifts, the original array will look like a=[1,4,3,2,5,6].
  • i=5: let’s say Petya decided to make 0 cyclic shifts, then the array won’t change.
  • i=6: let’s say Petya decided to make 4 cyclic shifts, the array will look like a=[3,2,5,6,1,4].

You are given a final array state aa after all nn operations. Determine if there is a way to perform the operation that produces this result. In this case, if an answer exists, print the numbers of cyclical shifts that occurred during each of the nn operations.

Input

The first line of the input contains an integer tt (1≤t≤500) — the number of test cases in the test.

The descriptions of the test cases follow.

The first line of the description of each test case contains one integer nn (2≤n≤2⋅10^3) — the length of the array aa.

The next line contains the final state of the array aa: nn integers a1,a2,…,an (1≤ai≤n) are written. All aiai are distinct.

It is guaranteed that the sum of nn values over all test cases does not exceed 2⋅10^3.

Output

For each test case, print the answer on a separate line.

Print -1 if the given final value a cannot be obtained by performing an arbitrary number of cyclic shifts on each operation. Otherwise, print n non-negative integers d1,d2,…,dn (di≥0), where didi means that during the ii-th operation the first i elements of the array were cyclic shifted to the right didi times.

If there are several possible answers, print the one where the total number of shifts is minimal (that is, the sum of di values is the smallest). If there are several such answers, print any of them.

Example

input

Copy

3
6
3 2 5 6 1 4
3
3 1 2
8
5 8 1 3 2 6 4 7

output

Copy

0 1 1 2 0 4 
0 0 1 
0 1 2 0 2 5 6 2 

Note

The first test case matches the example from the statement.

The second set of input data is simple. Note that the answer [3,2,1] also gives the same permutation, but since the total number of shifts 3+2+1 is greater than 0+0+1, this answer is not correct.

这题是说,给你一个长度为n的数组,这个数组的元素组成是 1, 2 …… n-1, n ;而且原本顺序也该是这样子的,即从1到n的单调递增函数,但经历了一些操作后变成了它给的这样,问当初的数组是经过了什么样的变化变成了如今的样子,让你输出变化的数组。

变化的方法是,从i=1开始到i=n,每次取数组的前i个元素进行旋转,比如i是3,数组是1 2 3 4 5,那就是取前三个元素1 2 3进行旋转,旋转的次数你来决定,如果旋转一次,那就是变成3 1 2,这样原来数组就是3 1 2 4 5了,由此类推。而你要输出的变化的数组就是,当选中前i个数后,旋转的次数。

既然它是原本有序的数组经过一系列变化变成了如今无序的样子,那我们反着来,只要反着操作,我们就可以用原来的变化顺序把现在的数组变回之前有序的情况,怎么反着来,原来变化的时候,每次选前i个数,i的取值是从1n递增,那我们只要从n1递减即可,而且之前旋转,都是向右旋转(1 2 3变成了3 1 2,我们就向左旋转 1 2 3变成2 3 1),然后就是把每个数移动到对应的位置上即可,如果是三,就把它放到下标为2的地方(下标从0开始),如果是5就放到下标为4的位置。那么我们该怎么做呢。

首先我们前面说了,我们每次取前i个数进行旋转对吧,而且i的取值是从大到小的,比如数组2 3 5 4 1,我们第一次是选前5个数进行旋转,第二次是选前4个数进行旋转,你应该发现了,如果我们想复原第五个位置上的数,只有一个机会,那就是在旋转前5个数的时候,把5这个数移动到第五个位置上,毕竟之和就算进行旋转,也不会再影响到第五个位置上的数了。此时做法就很明显了,我们每次遍历前i个数,找到对应的那个数,比如2 3 5 4 1这个数组,5在下标为2的位置上,那么我们就是要旋转2+1=3次,才能把数字5放在第五个位置上,此时数组为4 1 2 3 5,这样就算完成了第一步,变幻数组(我们最后要输出的那个)第5个位置上的值就是我们旋转的次数:2+1=3。然后我们如法炮制继续找到其他的数即可。要注意的是,如果要找的数已经在它应该在的位置上了,那我们不进行任何操作,变换数组对应位置上的值也就是0.

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>
 
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 200010;
ll f[N], s[N], e[N];
 
 
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		cin >> n;
		vector<int>v(n), res(n);
		for (int i = 0; i < n; i++)cin >> v[i];
		for (int i = n - 1; i >= 0; i--)
		{
			int ans = -1;
			for (int j = 0; j <= i; j++)
			{
				if (v[j] == i+1)
				{
					ans = j;
					break;
				}
			}
			if (ans!=-1&&v[ans] == ans + 1)continue;
			res[i] = ans + 1;
			vector<int>v1;
			v1.assign(v.begin(), v.begin() + (ans + 1));
			int l = 0;
			for (int j = ans + 1; j <= i; j++)
				v[l++] = v[j];
			for (auto i : v1)
			{
				v[l++] = i;
			}
		}
		for (int i = 0; i < n; i++)cout << res[i] << " ";
		cout << endl;
	}
 
 
	return 0;
}
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值