Petya and Construction Set
题解
一个构造题,结论挺容易猜的。观察到关键信息:\(d_i\le n\)。所以我们先把所有奇数编号的点按对应的 \(d\) 从大到小组成一条链,然后依次考虑偶数号点应该接在链上的哪个点后,容易知道这个点为链上的第 \(i+d-1\) 个。特殊的,如果接在了最后一个点后面,我们就更新链的长度。
我可以告诉你,这是对的,证明如下(感觉比另一篇的证明简单些):
我们用归纳法。
-
第一个点一定能找到对应的位置,这是因为 \(d_i\le n\)。
-
假设第 \(i-1\) 个点找到了对应位置,那么第 \(i\) 个点也可以找到对应位置,这是因为第 \(i-1\) 个点找到了对应位置就意味着从第 \(i-1\) 个点往后,至少存在 \(d_{i-1}\) 个点,而 \(d_i\le d_{i-1}\),所以我们要找 \(i\) 后第 \(d_i-1\) 个点一定存在。
-
可推广至 \(n\)。
代码已经短到一种境界了:
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int rd() {
int s=0,m=0;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-')m=1;ch=getchar();}
while( isdigit(ch)) s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return m?-s:s;
}
int n,l[200005],cnt;
struct QWQ {int id,d;} a[200005];
bool cmp(QWQ a1,QWQ a2) {return a1.d>a2.d;}
signed main() {
cin>>n;
for(int i=1;i<=n;i++)
a[i]={i,rd()};
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
l[++cnt]=a[i].id*2-1;
for(int i=1;i<n;i++)
printf("%lld %lld\n",l[i],l[i+1]);
for(int i=1;i<=n;i++) {
int j=i+a[i].d-1;
printf("%lld %lld\n",l[j],a[i].id*2);
if(j==cnt)
l[++cnt]=a[i].id*2;
}
return 0;
}
标签:ch,个点,int,题解,le,CF1214E,对应
From: https://www.cnblogs.com/operator-/p/17974756