Codeforces#642 (Div. 3) D. Constructing the Array

题目链接

题意:

给一个长度为n的空序列,然后往里面填1-n的数字;

int cnt=1;
找序列中最长(如果多个最长则取最左边的序列)的连续全空区间:并且赋值cnt++;循环这个操作n次:

eg:
Consider the array a of length 5 (initially a=[0,0,0,0,0]). Then it changes as follows:

Firstly, we choose the segment [1;5] and assign a[3]:=1, so a becomes [0,0,1,0,0];
then we choose the segment [1;2] and assign a[1]:=2, so a becomes [2,0,1,0,0];
then we choose the segment [4;5] and assign a[4]:=3, so a becomes [2,0,1,3,0];
then we choose the segment [2;2] and assign a[2]:=4, so a becomes [2,4,1,3,0];
and at last we choose the segment [5;5] and assign a[5]:=5, so a becomes [2,4,1,3,5].

分析:

一开始做法是开两个queue,算是一个贪心做法,但是发现难以处理不同批次的同长度区间;于是想到了优先队列写法

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
//
using namespace std;
const int INF = 0x3f3f3f3f;//1.06e9大小
const int mod1 = 1e9 + 7;
const int mod2 = 998244353;
const int mod3 = 1e9;
const double PI = 3.14159265;
const double eps =1e-10;
typedef unsigned long long ULL;
typedef long long LL;
#define debug printf("**debug**\n")
#define ms(x, n) memset(x,n,sizeof(x))
/*
*/
struct node
{
	int l,r;
	int w;
	bool operator < (const node a) const
	{
		if(w==a.w)
			return l>a.l;
		return w<a.w;
	}
};
int a[200001];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		priority_queue<node>q;
		q.push({1,n,n-1+1});
		int cnt=1;
		while(!q.empty())
		{
			auto t=q.top();
			q.pop();
			int l=t.l,r=t.r;
			if((r-l+1)%2)
			{
				a[(l+r)/2]=cnt++;
				if(l<(l+r)/2)q.push({l,(l+r)/2-1,((l+r)/2-l)});
				if(r>(l+r)/2)q.push({(l+r)/2+1,r,(r-(l+r)/2)});
			}
			else
			{
				a[(l+r-1)/2]=cnt++;
				if(l<(l+r-1)/2)q.push({l,(l+r-1)/2-1,((l+r-1)/2-l)});
				if(r>(l+r-1)/2)q.push({(l+r-1)/2+1,r,r-(l+r-1)/2});
			}
		}
		for(int i=1;i<=n;i++)
		{
			printf("%d ",a[i]);
		}
		printf("\n");
	}
	return 0;
}

对于优先队列维护结构体的数值的时候,我们写法也会像sort(from,to,cmp)的cmp重载一样:

struct node
{
	int l,r;
	int w;
	bool operator < (const node a) const
	{
		if(w==a.w)
			return l>a.l;
		return w<a.w;
	}
};

用{内容}重载运算符‘<‘;

这个写法因为右边是堆顶 (队列首), 又是大根堆,于是<,然后用{比较内容}重载这个运算符;

你可能感兴趣的:(Div题解)