[codeforces 1364B] Most socially-distanced subsequence 绝对值脱壳的4种形态

Codeforces Round #649 (Div. 2)  参与排名人数11286

[codeforces 1364B]   Most socially-distanced subsequence   绝对值脱壳的4种形态

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1364/problem/B

ProblemLangVerdictTimeMemory
B - Most socially-distanced subsequence GNU C++17Accepted46 ms800 KB

题目大意:给定数组a,可以删除任意元素,要求剩下的元素,相邻差值绝对值和最大,对应的剩下元素的个数最少,输出最少个数。

|x-y|+|y-z|

1.|x-y|脱壳情况如下

x>=y,|x-y|=x-y

x<=y,|x-y|=y-x

2.|y-z|脱壳情况如下

y>=z,|y-z|=y-z

y<=z,|y-z|=z-y

3.|x-y|+|y-z|脱壳情况如下

有4种组合

x>=y,y>=z

|x-y|+|y-z|=x-y+y-z=x-z此种情况,可删除元素y

x>=y,y<=z

|x-y|+|y-z|=x-y+z-y=x+z-2*y

x<=y,y>=z

|x-y|+|y-z|=y-x+y-z=2*y-(x+z)

x<=y,y<=z

|x-y|+|y-z|=y-x+z-y=z-x此种情况,可删除元素y

按上述思路,采用栈(在连续数据中,有目的的选取部分数据,用栈比较合适)的方式,编写的AC代码如下

#include <stdio.h>
#define maxn 100010
int a[maxn],st[maxn],top;
void solve(){
	int i,x,y,z,n;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	top=0;
	for(i=1;i<=n;i++){
		while(top>=2){
			x=st[top-1],y=st[top],z=i;
			if((a[x]>=a[y]&&a[y]>=a[z])||(a[x]<=a[y]&&a[y]<=a[z]))top--;
			else break;
		}
		st[++top]=i;
	}
	printf("%d\n",top);
	for(i=1;i<=top;i++)printf("%d ",a[st[i]]);
	printf("\n");
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--)solve();
	return 0;
}

按上述思路,采用再开一个数组用来存储剩下的数组元素,对应的AC代码,建议读者不用细读,只是告诉读者掌握数据结构有多么重要,懂和不懂,同一个思路,编出的代码差太多了。

ProblemLangVerdictTimeMemory
B - Most socially-distanced subsequence GNU C++17Accepted62 ms1900 KB
#include <stdio.h>
#define maxn 100010
int a[maxn],b[maxn],l[maxn],r[maxn],vis[maxn];
void solve(){
	int n,i,x,y,z,ans,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	for(i=1;i<=n;i++)vis[i]=0;
	if(n==2){
		printf("2\n");
		for(i=1;i<=n;i++)printf("%d ",a[i]);
		printf("\n");
		return ;
	}
	l[2]=1,y=2,r[2]=3,j=0;
	while(y+1<=n){//n>=3
		if((a[l[y]]>=a[y]&&a[y]>=a[r[y]])||(a[l[y]]<=a[y]&&a[y]<=a[r[y]])){
			y++;
			l[y]=l[y-1],r[y]=y+1;
			if(!vis[l[y-1]])vis[l[y-1]]=1,b[++j]=a[l[y-1]];
		}else{
			if(!vis[l[y]])vis[l[y]]=1,b[++j]=a[l[y]];
			if(!vis[y])vis[y]=1,b[++j]=a[y];
			y++,l[y]=y-1,r[y]=y+1;;
		}
	}
	b[++j]=a[y];
	printf("%d\n",j);
	for(i=1;i<=j;i++)printf("%d ",b[i]);
	printf("\n");
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--)solve();
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值