[codeforces 1353D] Constructing the Array 分治算法

Codeforces Round #642 (Div. 3)  参与排名人数11823

[codeforces 1353D]   Constructing the Array   分治算法

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址http://codeforces.com/contest/1353/problem/D

Problem Lang Verdict Time Memory
D - Constructing the Array GNU C++17 Accepted 77 ms 7500 KB

本场比赛最大收获,在比赛中悟出了分治算法(这个是弱项),并且AC掉该题。那种感觉真奇妙。

思路:

通过分治算法,找出所有可放数据的区间,将区间按区间长度,自大到小排序,若区间长度相同,按左边界自小到大排序。

之后,将放置的数据,按顺序放入安置区间对应的安置位置。

样例分析如下

n=6
(1,6)中的3位置可放置数据
(1,6)剩下的可放置数据的区间是(1,2),(4,6)

(1,2)中的1位置可放置数据
(4,6)中的5位置可放置数据

(1,2)剩下的可放置数据的区间是(2,2)
(2,2)中的2位置可放置数据

(4,6)剩下的可放置数据的区间是(4,4),(6,6)
(4,4)中的2位置可放置数据
(6,6)中的6位置可放置数据

可放置数据的区间如下
(1,6),a[3]=1
(4,6),a[5]=2
(1,2),a[1]=3
(2,2),a[2]=4
(4,4),a[4]=5
(6,6),a[6]=6

AC代码如下

#include 
#include 
using namespace std;
int a[200010],cnt,tot;
struct node{
	int left,right,mid,delta;//left记录区间左边界,right记录区间右边界,mid记录区间放置数据位置,delta记录区间长度
}b[200010];
int cmp(node a,node b){
	return a.delta==b.delta?a.leftb.delta;//将区间按区间长度,自大到小排序,若区间长度相同,按左边界自小到大排序。
}
void dfs(int left,int right){
	int mid;
	if(left>right)return;//结束条件
	tot++,b[tot].left=left,b[tot].right=right,b[tot].mid=(left+right)/2,b[tot].delta=right-left+1,mid=(left+right)/2;//记录安置区间的数据
	dfs(left,mid-1),dfs(mid+1,right);//区间分裂,请注意,mid位置已被占用,故mid-1,mid+1
}
int main(){
	int t,n,i;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(i=1;i<=n;i++)a[i]=0;//初始化
		for(i=1;i<=n;i++)b[i].left=b[i].right=b[i].delta=0;//初始化
		cnt=0,tot=0;//初始化,tot记录安置区间的数量
		dfs(1,n);//找出安置数据的区间
		sort(b+1,b+1+tot,cmp);//将区间按区间长度,自大到小排序,若区间长度相同,按左边界自小到大排序。
		for(i=1;i<=tot;i++)a[b[i].mid]=++cnt;//cnt是指需要放置的数据
		for(i=1;i<=n;i++)printf("%d ",a[i]);
		printf("\n");
	}
	return 0;
}

 

你可能感兴趣的:(codeforces)