1. 程式人生 > 其它 >#笛卡爾樹,構造#洛谷 7726 天體探測儀(Astral Detector)

#笛卡爾樹,構造#洛谷 7726 天體探測儀(Astral Detector)

笛卡爾樹,構造

題目傳送門


分析

考慮每個數字一定會影響一定的範圍,

那麼可以記錄每個數影響的最長區間和產生的個數,

那麼通過這個可以解方程求出對於這個最長區間這個數的所在位置,

可以發現它可以滿足一個樹形結構,直接用笛卡爾樹的方法遍歷出來即可


程式碼

#include <cstdio>
#include <cctype>
#include <stack>
#define rr register
using namespace std;
const int N=811; stack<int>st[N];
int a[N][N],L[N],R[N],n,fi[N],se[N],ls[N],rs[N]; 
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(int x){
	if (ls[x]) print(ls[x]);
	printf("%d ",x);
	if (rs[x]) print(rs[x]);
}
signed main(){
	n=iut();
	for (rr int i=1;i<=n;++i)
	for (rr int j=1;j<=n-i+1;++j)
	    ++a[i][iut()];
	for (rr int i=1;i<=n;++i)
	for (rr int j=1;j<=n-i+1;++j)
	    if (a[i][j]) L[j]=i,R[j]+=a[i][j];
	for (rr int i=1;i<=n;++i){
		for (rr int j=0;j<L[i];++j)
		if ((j+1)*(L[i]-j)==R[i])
			{fi[i]=j,se[i]=L[i]-j-1; break;}
	}
	for (rr int i=n;i;--i){
		if (!st[fi[i]].empty()) ls[i]=st[fi[i]].top(),st[fi[i]].pop();
		if (!st[se[i]].empty()) rs[i]=st[se[i]].top(),st[se[i]].pop();
		st[L[i]].push(i);
	}
	print(1);
	return 0; 
}