cf #779 div2 思维 C. Shinju and the Lost Permutation
题意:
定义一个前缀最大数组的概念,如{5,4,3,6,1,2},覆盖后变为{5,5,5,6,6,6}(从前往后大的覆盖小的) 得到的不同数的个数为当前排列的p值。
给出n和n个p值,问是否存在这种排列
思路:
6
1
1
2
1 2
2
2 2
6
1 2 4 6 3 5
6
2 3 1 2 3 4
3
3 2 1
看给定的输入和输出,稍微模拟,会发现最大的数在第一个位置的时候p为1。
如2 3 1 2 3 4
循环后把1放在最后一个位置 变成 1 2 3 4 2 3
我们可以用插入的办法维护一个数列
6
x,6
x-a,x,6
x-a-b,x-a,x,6
此时到2操作了,要使得只剩两个数,这个数一定是x<y<6的数,相当于把x-a-b,x-a,x全覆盖了(可以用栈或者队列来),即
y,6
接下来是3
y-a,y,6
符合
我们会发现,原来p的顺序应该是 要么比前面一个数大1(因为一次不可能增加>=2个),要么比前面一个数小或等于,并且一组p种只能有1个1。以此作为判断条件即可。
#include<bits/stdc++.h> using namespace std; signed main() { int t; cin>>t; while(t--) { int n; cin>>n; vector<int>a; for(int i=0;i<n;i++) { int num; cin>>num; a.push_back(num); } int flag=-1; for(int i=0;i<a.size();i++) { if(a[i]==1) { flag=i; break; } } if(flag==-1) { cout<<"NO"<<endl; continue; }else { vector<int>b; for(int i=flag;i<a.size();i++) { b.push_back(a[i]); } for(int i=0;i<flag;i++) { b.push_back(a[i]); } int fg=0; for(int i=1;i<b.size();i++) { if((b[i]==b[i-1]+1||b[i]<=b[i-1])&&b[i]>1) { continue; }else { fg=1; break; } } if(fg) { cout<<"NO"<<endl; } else { cout<<"YES"<<endl; } } } }
本文作者:TimMCBen
本文链接:https://www.cnblogs.com/TimMCBen/p/16066659.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步