2024/2/15

P1160 队列安排

题目描述

一个学校里老师要将班上 N 个同学排成一列,同学被编号为 1∼N,他采取如下的方法:

  1. 先将 11 号同学安排进队列,这时队列中只有他一个人;

  2. 2∼N 号同学依次入列,编号为 i 的同学入列方式为:老师指定编号为 i 的同学站在编号为 1∼(i−1) 中某位同学(即之前已经入列的同学)的左边或右边;

  3. 从队列中去掉 M 个同学,其他同学位置顺序不变。

在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。

输入格式

第一行一个整数 N,表示了有 N 个同学。

第 2∼N 行,第 i 行包含两个整数k,p,其中k 为小于 i 的正整数,p 为 0 或者 1。若 p 为 0,则表示将 i 号同学插入到 k 号同学的左边,p 为 1 则表示插入到右边。

第N+1 行为一个整数 M,表示去掉的同学数目。

接下来 M 行,每行一个正整数 x,表示将x 号同学从队列中移去,如果x 号同学已经不在队列中则忽略这一条指令。

输出格式

一行,包含最多 N 个空格隔开的整数,表示了队列从左到右所有同学的编号。

用双向链表来处理

#include<bits/stdc++.h>
using namespace std;
struct LN
{
	int callname;
	struct LN * front;
	struct LN * next;
};
int main()
{
	int n,m,p,k,num;
    while(scanf("%d",&n)!=EOF)//插入节点
    {
    	LN ** a=(LN **)calloc(n+1,sizeof(LN *));//定义结构体数组
    	int first=1;
    	for(int i=1;i<=n;i++)
    	{
    		a[i]=(LN *)calloc(1,sizeof(LN));
    		a[i]->callname=i;
    		a[i]->front=NULL;
    		a[i]->next=NULL;
		}
		LN* tmep;
		for(int i=2;i<=n;i++)
		{
			scanf("%d %d",&k,&p);
			if(k==first&&p==0)//第一个人
			{
				first=i;
			}
			if(p==0)//插入到左边
			{
				a[i]->next=a[k];//更新i同学的右侧
				a[i]->front=a[k]->front;//更新i同学左侧
				a[k]->front=a[i];//更新k同学左侧
				if(a[i]->front!=NULL)
				{
					a[i]->front->next=a[i];
				}
			}
			if(p==1)//插入到右边
			{
				a[i]->front=a[k];
				a[i]->next=a[k]->next;
				a[k]->next=a[i];
				if(a[i]->next!=NULL)
				{
					a[i]->next->front=a[i];
				}
			}
		}
		scanf("%d",&m);
		for(int i=1;i<=m;i++)
		{
			scanf("%d",&num);
			if(a[num]->callname==0)
			{
				continue;
			}
			if (first==num) first=a[num]->next!=NULL ? a[num]->next->callname : 0 ;
			if(a[num]->front!=NULL)
			    a[num]->front->next=a[num]->next;
			if(a[num]->next!=NULL)
			    a[num]->next->front=a[num]->front;
			 a[num]->front=NULL,a[num]->next=NULL,a[num]->callname=0;
		}
	for(tmep=a[first];tmep->next!=NULL;tmep=tmep->next)
		printf("%d ",tmep->callname);
	printf("%d\n",tmep->callname);
	for(int i=0;i<=n;i++)
		if(a[i]!=NULL)
			free(a[i]);
	free(a);
	}
	return 0;
}

P1996 约瑟夫问题

题目描述

n 个人围成一圈,从第一个人开始报数,数到 m 的人出列,再由下一个人重新从 11 开始报数,数到 m 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。

注意:本题和《深入浅出-基础篇》上例题的表述稍有不同。书上表述是给出淘汰 n−1 名小朋友,而该题是全部出圈。

输入格式

输入两个整数n,m。

输出格式

输出一行 n 个整数,按顺序输出每个出圈人的编号。

这次选择用循环链表来写这道题

#include<bits/stdc++.h>
using namespace std;
int next[1000005];
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)//初始化
    	next[i]=i+1;
	next[n]=1;
	int p=0;
	for(int i=1;i<=n;i++)
    {
		for(int j=1;j<m;j++)
			p=next[p];
		cout<<p[next]<<" ";
		next[p]=next[next[p]];
	}
	return 0;
}

P2080 增进感情

题目背景

小明和小红的感情,是慢慢发展起来的。

题目描述

他们对对方分别有一个好感值。定义两人的亲密程度为两人的好感值之和。

如果他们的亲密程度达到 v,则他们将走到一起。他们以后的生活将取决于两人的好感值之差的绝对值,这个值越小,他们的生活将越幸福。

现在,他们对对方的好感值都为 00,小明有 n 件事可以干,每件事可以增加他对小红的好感 ai​ 点,并且增加小红对他的好感 bi​ 点。(可能为负数)

小明可以任选一些事做,请你帮小明求出怎样才能让他们的生活更加幸福(求出两人在一起的前提下,好感值之差的最小绝对值即可)。

输入格式

第一行,两个正整数 n,v。

之后 n 行,每行两个空格隔开的整数 ai​,bi​。

输出格式

一行,一个非负整数,表示两人在一起的前提下,好感值之差的最小绝对值。如果无论如何两人也无法在一起,输出 -1

搜索

#include<bits/stdc++.h>
using namespace std;
int a[105],b[105],n,v,minn=1e9;
void dfs(int x,int y,int k)
{
	if(minn==0)
	{
		return;
	}
	if(k>n)
	{
		if(x+y>=v)
		{
			minn=min(minn,abs(x-y));
		}
		return;
	}
	dfs(x+a[k],y+b[k],k+1);
	dfs(x,y,k+1);
}
int main()
{
	cin>>n>>v;
	for(int i=1;i<=n;++i)
	{
		cin>>a[i]>>b[i];
	}
	dfs(0,0,1);
	if(minn<1e9)
	{
		cout<<minn;
	}
	else
	{
		cout<<-1;
	}
	return 0;
}

P1102 A-B 数对

题目背景

出题是一件痛苦的事情!

相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!

题目描述

给出一串正整数数列以及一个正整数 C,要求计算出所有满足A−B=C 的数对的个数(不同位置的数字一样的数对算不同的数对)。

输入格式

输入共两行。

第一行,两个正整数N,C。

第二行,N 个正整数,作为要求处理的那串数。

输出格式

一行,表示该串正整数中包含的满足 A−B=C 的数对的个数。

#include <bits/stdc++.h>
using namespace std;
long long n,c,sum;
int a[1000000];
int fun1(int x)
{
	int left=0,right=n+1,mid;
	while(1+left<right)
	{
		int mid=(left+right)/2;
		if(a[mid]<=x)
		{
			left=mid;
		}
		else
		{
			right=mid;
		}
	}
	return left;
}
int fun2(int x)
{
	int left=0,right=n+1,mid;
	while(1+left<right)
	{
		int mid=(left+right)/2;
		if(a[mid]<x)
		{
			left=mid;
		}
		else
		{
			right=mid;
		}
	}
	return left;
}
int main()
{
	int i;
	cin>>n>>c;
	for(i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	sort(a+1,a+1+n);
	for(i=1;i<=n;i++)
	{
		sum+=fun1(a[i]+c)-fun2(a[i]+c);
	}
	cout<<sum;
	return 0;
}

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值