Codeforces Round #773 (Div. 2) D

场上只做出3题,赛后看jiangly老师的代码过了D

真实的惊叹于jiangly老师思路的巧妙 & 代码的优美   %%%

jiangly老师视频链接

https://www.bilibili.com/video/BV1cT4y1Q7JC?from=search&seid=15138832520877575044&spm_id_from=333.337.0.0

题目链接

https://codeforces.com/contest/1642/problem/D

做法

就不说错误的思路了,总之就是找不到问题关键所在,写了假算法

如果在数组中间插入数会对之后的数下标产生影响,因此插入操作考虑从后往前做。

从现有的数组的最末尾开始(position:i),找到前一个和它一样的数(position:j),往j之后插入i与j中间的数

这里的插入不是真的往数组里面插入数,是加进答案;

真实发生的事情是去掉i和j处的数,然后把它们中间部分的数翻转(结合本题题意理解)

这样可以大大简化代码的写法

细节见代码

放一下我参考jiangly老师的代码写的代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,t,x,q,d;
map<int,int>mp;

int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		vector<int>a;
		for(int i=1,x;i<=n;i++){
			scanf("%d",&x);
			a.push_back(x);
		}
		
		vector<pair<int,int>>ans;
		vector<int>len;
		bool f=1;
		while(!a.empty()){
			int i=a.size()-1;
			int j=i-1;
			while(j>=0&&a[i]!=a[j]){
				j--;
			}
			if(j==-1){
				f=0;
				puts("-1");
				break;
			}
			
			for(int k=0;k<i-j-1;k++){
				ans.push_back(make_pair(j+k,a[i-1-k]));
			}
			len.push_back(2*(i-j));
			reverse(a.begin()+j+1,a.begin()+i);
			a.pop_back();
			a.erase(a.begin()+j);
			
		}
		if(!f) continue;
		
		printf("%d\n",ans.size());
		for(int i=0;i<ans.size();i++){
			printf("%d %d\n",ans[i].first,ans[i].second);
		}
		
		reverse(len.begin(),len.end());
		printf("%d\n",len.size());
		for(int i=0;i<len.size();i++){
			printf("%d ",len[i]);
		}
		puts("");
	}
	return 0;
} 

 

上一篇:MySQL主从双向同步复制


下一篇:将svnserve部署为后台服务