C题 Psychos in a Line CodeForces - 320D
博客链接:https://blog.csdn.net/zvenWang/article/details/84714945
题意:就是给定一行精神病人,他们每个人都有自己的某种数值,如果当前位置的右侧的人的数值小于它,那么它会杀死它右侧的那个人,且存在连续杀性质(能够将这个性质在一个时间单位下进行传递)
思路:发现这其实是类似于单调栈的操作。大体的思想是,从后往前遍历数组,ans数组记录杀到能杀的人需要的步数
附上代码:
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stdlib.h>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#define lson rt << 1,l , mid
#define rson rt << 1 | 1,mid + 1 , r
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 1e5+10;
const int inf = 0x3f3f3f3f;
typedef long long ll;
//const int mod=1e4+7;
const double eps=1e-6;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<='0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
int num[maxn],ans[maxn];
int n;
stack<int>s;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&num[i]);
}
for(int i=n;i>=1;i--){
if(s.empty()){
s.push(num[i]);
ans[num[i]]=0;
continue;
}
if(s.top()>num[i]){
s.push(num[i]);
ans[num[i]]=0;
}
else if(s.top()<=num[i]){
int temp=max(1,ans[s.top()]);
s.pop();
while(!s.empty()&&s.top()<=num[i]){
temp=max(temp+1,ans[s.top()]);
s.pop();
}
ans[num[i]]=temp;
s.push(num[i]);
}
}
int maxx=0;
for(int i=1;i<=n;i++){
maxx=max(maxx,ans[num[i]]);
}
printf("%d\n",maxx);
}
D题 Sequence Sorting CodeForces - 1223D
博客链接:https://blog.csdn.net/qq_43627087/article/details/102291345
题意:给出一个序列,有两种操作可以把所有相同的数字挪到队首或者队尾。问最少操作几次可以保证这个序列是一个非降序列。
思路:第一反应这是道dp的题,但是仔细想一想,我们只需要记录一个元素的第一次出现的位置和最后一次出现的位置,然后记录有多少不同的元素。我们不找需要操作的元素,而是找不用操作的元素,用总的元素减去不用操作的就是答案。
附上代码:
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stdlib.h>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#define lson rt << 1,l , mid
#define rson rt << 1 | 1,mid + 1 , r
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 3e5+10;
const int inf = 0x3f3f3f3f;
typedef long long ll;
//const int mod=1e4+7;
const double eps=1e-6;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<='0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
int q;
int n;
int num[maxn];
int l[maxn],r[maxn];
//l数组记录某一元素第一次出现的位置,r数组记录某一元素最后一次出现的位置
int main(){
scanf("%d",&q);
while(q--){
scanf("%d",&n);
for(int i=1;i<=n;i++){//用memset初始化会TLE,q和n的范围都是3e5
l[i]=r[i]=0;
}
for(int i=1;i<=n;i++){
scanf("%d",&num[i]);
if(l[num[i]]==0)l[num[i]]=i;
r[num[i]]=i;
}
int sum=0,ans=0;
int cnt=0,flag=0;
for(int i=1;i<=n;i++){
if(l[i]){
sum++;//有几个不同的元素
if(flag<l[i]){
cnt++;
}
else{//最差的情况是只有一个元素不用进行交换
cnt=1;
}
ans=max(ans,cnt);//ans用来记录最多不用进行交换的个数
flag=r[i];
}
}
printf("%d\n",sum-ans);
}
}