首页 > 其他 > 详细

Codeforces 1353D - Constructing the Array

时间:2020-05-15 09:05:27      阅读:141      评论:0      收藏:0      [点我收藏+]

题面

技术分享图片




题意

一个长度为 n 的数组,初始值全部为 0

每次选择其中最长的一段全0连续子数组,如果多个并列最长,取最左边的那个,并标记其左右区间 L R

如果这个子数组包含的元素个数为奇数(R-L+1为奇数),则将这一段区间最中间那个位置标记上数字

如果这个子数组包含的元素个数为偶数,则将这一段区间内中间靠左的那个位置标记上数字

数字依次标记 1~n,最后输出这个数组




解题思路

可以采用搜索的方法

建立结构体后,用优先队列来把个数最多的、个数相同区间靠左的放在队列的前端

每次取队列前端的元素出队列处理即可(类似线段树建树)

 注意使用优先队列时需要重载大于运算符




完整程序

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

struct node
{
	int siz,l,r;
	bool operator > (const node& a) const //优先队列重载大于运算符
	{
		if(siz!=a.siz)
			return siz<a.siz; //将区间包含的元素较多的放在前面
		return l>a.l; //相同个数则将left小的放在前面
	}
};

int ar[200050];
void solve()
{
    int n,tmp=1,mid,l,r;
    cin>>n;
    
    priority_queue<node,vector<node>,greater<node> > q;
    q.push(node{n,1,n});
    
    while(!q.empty())
	{
		node nd=q.top();
		q.pop();
		l=nd.l;
		r=nd.r;
		if(l==r) //如果区间只包含一个元素,直接赋值即可
			ar[l]=tmp++;
		else
		{
			if((r-l)&1)
				mid=(r+l-1)>>1;
			else
				mid=(r+l)>>1;
			
			ar[mid]=tmp++; //给题意描述的位置赋值
			
			//接下来相当于讨论[l,r]区间去掉mid后形成的两个区间
			if(l<mid) //如果[l,mid-1]区间存在
				q.push(node{mid-l,l,mid-1});
			if(r>mid) //如果[mid+1,r]区间存在
				q.push(node{r-mid,mid+1,r});
		}
	}
	for(int i=1;i<=n;i++)
		cout<<ar[i]<<‘ ‘;
	cout<<‘\n‘;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;cin>>T;
    for(int t=1;t<=T;t++)
        solve();
    return 0;
}

Codeforces 1353D - Constructing the Array

原文:https://www.cnblogs.com/stelayuri/p/12892451.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!