ACM寒假集训第三次专题任务

ACM寒假集训第三次专题任务

一、Priority Queue

题目:

联想截图_20250207141553

解题思路:

对优先队列的直接运用,直接翻译题目即可。

AC代码:

#include<iostream>
#include<string>
#include<queue>
using namespace std;
int main()
{
	int k;
	string operation;
	priority_queue<int> S;
	while(1)
	{
		cin>>operation;
		if(operation=="insert")
		{
			cin>>k;
			S.push(k);
		}
		else if(operation=="extract")
		{
			if(!S.empty())
			{
				cout<<S.top()<<endl;
				S.pop();
			}
		}
		else if(operation=="end")
		{
			break;
		}
	}
	return 0;
}

二、ST 表 && RMQ 问题

题目:

联想截图_20250207142105联想截图_20250207142125

解题思路:

先构建ST表(以Sample 1为例):

1 2 3 4 5 6 7 8
i=0 9 3 1 7 5 6 0 8
i=1 9 3 7 7 6 6 8
i=2 9 7 7 7 8
i=3 9

再输入l和r,判断l到r整个区间的长度,取对数得到小于此长度的最大i(2的i次方,例如,9对应i为3,因为2的3次方为8,而8是小于9的。当i取4时则得到16大于9,不合题意)。

然后判断第一段、第二段起末位置并比较大小。

AC代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
int N,M,l,r,a[31][100005],len;
int main()
{
	scanf("%d%d",&N,&M);
	for(int i=1;i<=N;i++)
	{
		scanf("%d",&a[0][i]);
	}
	len=log2(N);
	for(int i=1;i<=len;i++)
	{
		for(int j=1;j<=N-(1<<(i-1));j++)
		{
			a[i][j]=max(a[i-1][j],a[i-1][j+(1<<(i-1))]);
		}
	}
	while(M--)
	{
		scanf("%d%d",&l,&r);
		len=log2(r-l+1);
		printf("%d\n",max(a[len][l],a[len][r-(1<<len)+1]));
	}
	return 0;
}

三、合并果子

题目:

联想截图_20250207142257联想截图_20250207142325

解题思路:

论小根堆的运用,只要把每轮最小的两个加起来并都予去除,再push两者之和进堆即可。

AC代码:

#include<iostream>
#include<queue>
#include<functional>
#include<vector>
using namespace std;
int n,sum,t,k;
priority_queue<int,vector<int>,greater<int>> a;
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>k;
		a.push(k);
	}
	while(a.size()!=1)
	{
		t=0;
		t+=a.top();
		a.pop();
		t+=a.top();
		sum+=t;
		a.pop();
		a.push(t);
		
	}
	cout<<sum;
}

四、约瑟夫问题

题目:

联想截图_20250207142426

解题思路:

论队列的运用,把跳过的人从队首调到对尾,出圈的人则输出并从队伍中删除。

AC代码:

#include<iostream>
#include<queue>
using namespace std;
int n,m;
queue<int> a;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		a.push(i);
	}
	while(!a.empty())
	{
		for(int i=1;i<m;i++)
		{
			int t=a.front();
			a.pop();
			a.push(t);
		}
		cout<<a.front()<<" ";
		a.pop();
	}
	return 0;
}

五、Look Up S

题目:

联想截图_20250207142514联想截图_20250207142543

解题思路:

单调栈的运用,相当于一次遍历找所有数的下一最近的大于此数的数的位置。

先把第一个数放进栈,第二个数若比它大,则其为第一个数对应所求;若比它小,则不是,并将第二个数也放进栈。如果第三个数大于第一个数,那么它既为第一个数对应答案也是第二个数对应答案,则将第一个数与第二个数从栈中消去(因为已经找到它们的答案了)。以以上思路进行循环即可得答案。

循环结束后仍在栈中的数则没有对应答案,输出0。

AC代码:

#include<iostream>
#include<vector>
#include<stack>
using namespace std;
struct cow{
	int h;
	int code;
};
int main()
{
	int n;
	cin>>n;
	vector<int> v(n+1),ans(n+1,0);
	stack<cow> s;
	for(int i=1;i<=n;i++)
	{
		cin>>v[i];
	}
	for(int i=1;i<=n;i++)
	{
		if(s.empty()||v[i]<=s.top().h)
		{
			s.push(cow{v[i],i});
		}
		else
		{
			while(!s.empty()&&v[i]>s.top().h)
			{
				ans[s.top().code]=i;
				s.pop();
			}
			s.push(cow{v[i],i});
		}
	}
	while(!s.empty())
	{
		ans[s.top().code]=0;
		s.pop();
	}
	for(int i=1;i<=n;i++)
	{
		cout<<ans[i]<<endl;
	}
	return 0;
}

六、国旗计划

题目:

联想截图_20250207142626联想截图_20250207142641

解题思路:

环的问题,2倍链处理。结构体输入战士信息。假设对i战士进行分析,其右端点为r[i],那么下一个战士j要符合条件:

  1. l[j]≤r[i],保证能够覆盖要求

  2. r[j]尽量大,这是为了能够最优

用ST表进行处理

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 2e5 + 5;
int n, m;
int ans[MAXN];
int f[MAXN*2][20];
struct node {
    int id;
    int l, r;
} s[MAXN*2];
bool cmp(node a, node b) {
    return a.l < b.l;
}
void pre() {
    for (int i = 1, p = i; i <= 2 * n; i++) {
        while (p <= 2 * n && s[p].l <= s[i].r) {
            p++;
        }
        f[i][0] = p - 1;
    }
    for(int i = 1; i < 20; i++) {
        for(int j = 1; j <= 2 * n; j++) {
            f[j][i] = f[f[j][i-1]][i-1];
        }
    }
}
void solve(int k) {
    int rr = s[k].l + m;
    int tot = 1;
    int p = k;
    for (int i = 19; i >= 0; i--) {
        if (f[k][i] != 0 && s[f[k][i]].r < rr) {
            tot += (1 << i);
            k = f[k][i];
        }
    }
    ans[s[p].id] = tot + 1;
}
int main(){
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d %d", &s[i].l, &s[i].r);
        if (s[i].r < s[i].l) {
            s[i].r += m;
        }
        s[i].id = i;
    }
    sort(s + 1, s + 1 + n, cmp);
    for(int i = 1; i <= n; i++) {
        s[i + n] = s[i];
        s[i + n].l = s[i].l + m;
        s[i + n].r = s[i].r + m;
    }
    pre();
    for(int i = 1; i <= n; i++) {
        solve(i);
    }
    for(int i = 1; i <= n; i++) {
        printf("%d ", ans[i]);
    }
    return 0;
}

学习总结

学习了一些数据结构

stack

头文件#include <stack>

image-20250207225907538

定义:stack<int> s;

queue

头文件#include <queue>

image-20250207225956749image-20250207230012154

定义:queue<int> q;

priority_queue

头文件#include <queue>

image-20250207230103126

定义:priority_queue<int> q;默认为大根堆

定义小根堆:priority_queue<int, vector<int>,greater<int> > p;

ST表

详细使用见二、ST 表 && RMQ 问题。

posted @ 2025-02-07 23:22  cytlllll  阅读(31)  评论(0)    收藏  举报