2021-2022 ACM-ICPC Brazil Subregional Programming Contest (队列操作)

2021-2022 ACM-ICPC Brazil Subregional Programming Contest

E. Escalator

分析:

  • 这题没什么,就是一个队列的模拟

    然后,一直被绕来绕去,不知道如何去维护当前的时间,与每个人到达时间的关系

    不清楚,在何时,电梯实现状态的转换,从上升到下降 OR 下降到上升

  • 电梯上升和下降两种状态,分两类

  • 状态的转换:

    仔细想假设现在电梯在上升,要实现状态的转换,分两种情况:

    • 上升队列当中已经没人了
    • 下一个要上升的人的到达时间,超过了电梯停止的时间
#include <bits/stdc++.h>
using namespace std;

priority_queue <int, vector<int>, greater<int> > q,p;
// 没必要用优先队列,题目已经保证了从小到大
signed main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) 
	{
		int t,fg;
		cin>>t>>fg;
		if(fg) q.push(t);
		else p.push(t);
	}
	int t=0,ans=0;
	while(!q.empty() && !p.empty())
	{
		int up=q.top(),down=p.top();
		// 就分两类情况讨论
		if(up<down)
		{
            ans+=10;
            while(!q.empty() && q.top()<ans) 
            { 
                // q.top()>ans 即下一个人的到达时间超过的停止的时间 
                if(q.top()+10>ans) ans=q.top()+10;
                q.pop();
            }
		}
		else 
		{
            ans+=10;
            while(!p.empty() && p.top()<ans)
            {
                if(p.top()+10>ans) ans=p.top()+10; 
                p.pop();
            }
		}
	}
	// 经上述处理之后,必然有一个队列不为空
    ans+=10;
    int r=0;
    while(!q.empty()) r=q.top()+10,q.pop();
    while(!p.empty()) r=p.top()+10,p.pop(); 
	cout<<max(ans,r)<<endl;
}

G. Getting in Shape

分析:

  • 可以发现一串a加一个B的方案数就是斐波那契数列
  • 用一个b还是多个b隔开,效果一样,又因为题目要保证字典序最小,所以一个b就行了
  • 然后就是多个”一串a加一个b“的组合了,方案数为累乘
  • 预处理斐波那契数列,再跑一边 D F S DFS DFS 即可,
#include <bits/stdc++.h>
#define int long long
using namespace std;

int f[105];
void init()
{
	f[0]=f[1]=1;
	for(int i=2;i<=72;i++) f[i]=f[i-1]+f[i-2];
}
int ans[105];
int fg;
void dfs(int u,int tot,int l)
{
	if(u==1) 
	{
		fg=1;
		for(int i=1;i<tot;i++)
		{
			for(int j=1;j<=ans[i];j++) cout<<'A';
			cout<<'B';
		}
		return ;
	}
	for(int i=l;i>=2;i--)
	{
        // 注意:当前要找的因子,必定小于等于之前的因子,故i从l开始遍历
        // 不然就会超时,一直在反复遍历
		if(!fg && u%f[i]==0) 
		{
			ans[tot]=i-1;
			dfs(u/f[i],tot+1,l=i);
		}
	}
}
signed main()
{
	int n;
	cin>>n;
	if(n==1) { cout<<"A"<<endl; return 0; }
	init();
	dfs(n,1,72);
	if(!fg) cout<<"IMPOSSIBLE"<<endl;
}

M. Monarchy in Vertigo

分析:

  • 首先,要读懂题,发现要找的就是 D F S DFS DFS

    多了一些操作:过程当中去掉某些节点,让求的便是过程当中的 D F S DFS DFS 序的首节点

  • 用队列 + + + v i s vis vis 标记维护即可

#include <bits/stdc++.h>
using namespace std;

const int N=1e5+5;
vector <int> g[N];
int b[N];
queue <int> q;
void dfs(int u)
{
    for(int v : g[u])
    {
        q.push(v); 
        dfs(v);
    }
}
int vis[N];
signed main()
{
    int n;
    scanf("%d",&n);
    int tot=1,cnt=0;
    for(int i=1;i<=n;i++)
    {
        int t,x;
        scanf("%d%d",&t,&x);
        if(t==1) g[x].push_back(++tot);
        else b[++cnt]=x;
    }
    q.push(1);
    dfs(1);
    int now=1;
    for(int i=1;i<=cnt;i++)
    {
        vis[b[i]]=1;
        if(vis[now])
        {
            int u=q.front();
            while(!q.empty() && vis[u])
            {
                q.pop();
                u=q.front();
            }
            now=u;
        } 
        printf("%d\n",now);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yezzz.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值