https://atcoder.jp/contests/agc005/tasks/agc005_c
感觉这题去年某场cf E题好像见过啊
到最远的通过树的直径的求法可以知道每个点到最远点一定会使某条树的直径的端点
那么最大值首先一定要有两个,然后我们把这条直径链全构造出来
如果构造不满一条直径,就无解,如果最远点距离小于直径的一半就无解,然后注意样例中提醒了我们直径中间的点也就是最小的最大距离数量是确定的,不可以接上某个点成一个分叉,必须只能是直径上的点
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=3e5+10;
int n,m,cnt,tot,cas,ans;
int a[maxl],b[maxl];
bool vis[maxl];
char s[maxl];
vector<int> e[maxl];
inline void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
}
inline void mainwork()
{
int mx=0;
for(int i=1;i<=n;i++)
mx=max(mx,a[i]);
for(int i=1;i<=n;i++)
if(a[i]==mx)
{
if(!b[1])
b[1]=i,vis[i]=true;
else
{
b[mx+1]=i;vis[i]=true;
break;
}
}
ans=1;
if(b[mx+1]==0)
ans=0;
int mi=(mx+1)/2;
for(int i=1;i<=n;i++)
if(a[i]<mi)
ans=0;
else if(a[i]==mi)
{
if(vis[i])
continue;
if(!b[mx+1-a[i]])
b[mx+1-a[i]]=i;
else if(!b[1+a[i]])
b[1+a[i]]=i;
else
ans=0;
}
else
{
if(!b[mx+1-a[i]])
b[mx+1-a[i]]=i;
else if(!b[1+a[i]])
b[1+a[i]]=i;
}
for(int i=1;i<=mx+1;i++)
if(!b[i])
ans=0;
}
inline void print()
{
if(ans)
puts("Possible");
else
puts("Impossible");
}
int main()
{
int t=1;
//scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}