Urozero Autumn 2016. BAPC 2016

A. Airport Logistics

根据光路最快原理以及斯涅尔定律,可以得到从定点$P$进入某条直线的最佳入射角。

求出每个端点到每条线段的最佳点,建图求最短路即可。

时间复杂度$O(n^2\log n)$。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef pair<double,int>PI;
const int N=41000,M=1000000;
const double eps=1e-9,inf=1e100;
int n,cnt,i,j,g[N],v[M],nxt[M],ed;double w[M],d[N],va,vb,si[2],co[2];
priority_queue<PI,vector<PI>,greater<PI> >q;
inline void add(int x,int y,double z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
inline void add2(int x,int y,double z){add(x,y,z),add(y,x,z);}
inline void ext(int x,double y){if(y+eps<d[x])q.push(PI(d[x]=y,x));}
inline int sgn(double x){
  if(x>eps)return 1;
  if(x<-eps)return -1;
  return 0;
}
struct P{
  double x,y;
  P(){}
  P(double _x,double _y){x=_x,y=_y;}
  P operator+(P b){return P(x+b.x,y+b.y);}
  P operator-(P b){return P(x-b.x,y-b.y);}
  P operator*(double b){return P(x*b,y*b);}
  P operator/(double b){return P(x/b,y/b);}
  double operator*(P b){return x*b.x+y*b.y;}
  bool operator==(P b){return !sgn(x-b.x)&&!sgn(y-b.y);}
  double len(){return hypot(x,y);}
  P rotate(double s,double c){return P(x*c-y*s,x*s+y*c);}
  P rot90(){return P(-y,x);}
}a[210];
struct E{
  double x;int y;
  E(){}
  E(double _x,int _y){x=_x,y=_y;}
}e[410];
inline bool cmp(const E&a,const E&b){return a.x<b.x;}
inline double cross(P a,P b){return a.x*b.y-a.y*b.x;}
inline bool point_on_segment(P p,P a,P b){
  return sgn(cross(b-a,p-a))==0&&sgn((p-a)*(p-b))<=0;
}
inline P line_intersection(P a,P b,P p,P q){
  double U=cross(p-a,q-p),D=cross(b-a,q-p);
  return a+(b-a)*(U/D);
}
inline void work(int st,int en){
  int i,j,m=2;
  P A=a[st],B=a[en],C=(B-A).rot90();
  e[1]=E(0,st),e[2]=E(C.len(),en);
  for(i=0;i<=(n<<1|1);i++)if(i!=st&&i!=en)for(j=0;j<2;j++){
    P D=line_intersection(A,B,a[i],a[i]+C.rotate(si[j],co[j]));
    if(D==A||D==B)continue;
    if(!point_on_segment(D,A,B))continue;
    cnt++;
    add2(i,cnt,(a[i]-D).len()/vb);
    e[++m]=E((D-A).len(),cnt);
  }
  sort(e+1,e+m+1,cmp);
  for(i=1;i<m;i++)add(e[i].y,e[i+1].y,(e[i+1].x-e[i].x)/va);
}
int main(){
  scanf("%lf%lf",&a[0].x,&a[0].y);
  scanf("%lf%lf",&a[1].x,&a[1].y);
  scanf("%d",&n);
  va=2,vb=1;
  for(i=1;i<=n;i++){
    scanf("%lf%lf",&a[i<<1].x,&a[i<<1].y);
    scanf("%lf%lf",&a[i<<1|1].x,&a[i<<1|1].y);
  }
  si[0]=vb/va;
  co[0]=sqrt(1.0-si[0]*si[0]);
  si[1]=-si[0];
  co[1]=co[0];
  cnt=n<<1|1;
  for(i=0;i<=cnt;i++)for(j=0;j<i;j++)add2(i,j,(a[i]-a[j]).len()/vb);
  for(i=1;i<=n;i++)work(i<<1,i<<1|1);
  for(i=0;i<=cnt;i++)d[i]=inf;
  ext(0,0);
  while(!q.empty()){
    PI t=q.top();q.pop();
    if(t.first-eps>d[t.second])continue;
    for(i=g[t.second];i;i=nxt[i])ext(v[i],t.first+w[i]);
  }
  printf("%.10f",d[1]);
}

  

B. Battle Simulation

按题意模拟即可。

#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
const int top = 1e6;
const int N = top + 10, M = 262150;
char s[N], ans[N];

int main(){
    scanf("%s", s);
    int len = strlen(s);
    int num = 0;
    for(int i = 0; i < len; i ++){
        if(i + 2 < len && s[i] != s[i + 1] && s[i] != s[i + 2] && s[i + 1] != s[i + 2]){
            ans[++ num] = 'C';
            i += 2;
        }
        else if(s[i] == 'R') ans[++ num] = 'S';
        else if(s[i] == 'B') ans[++ num] = 'K';
        else ans[++ num] = 'H';
    }
    printf("%s\n", ans + 1);
}
/*
4
4 3
1 2
2 3
3 4
5
2 1 4
1 2 3
2 1 4
2 2 3
2 2 4
8 9
1 2
2 3
1 3
3 4
4 5
4 6
5 7
5 8
7 8
5
2 7 8
2 1 6
2 4 7
1 6 8
2 5 6
*/

  

C. Brexit

拓扑排序,不断删掉不合法的点即可。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 3e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n, m, ME, ST;
vector<int>a[N];
bool stay[N];
int ind[N];
int least[N];
int sta[N];
int main()
{
	while(~scanf("%d%d%d%d", &n, &m, &ME, &ST))
	{
	    for(int i = 1; i <= n; ++i)
        {
            a[i].clear();
            stay[i] = 1;
            ind[i] = 0;
        }
        for(int i = 1; i <= m; ++i)
        {
            int x, y; scanf("%d%d", &x, &y);
            a[x].push_back(y);
            a[y].push_back(x);
            ++ind[x];
            ++ind[y];
        }
        for(int i = 1; i <= n; ++i)
        {
            least[i] = ind[i] / 2 + 1;
        }
        int top = 0;
        sta[++top] = ST;
        stay[ST] = 0;

        while(top)
        {
            int x = sta[top--];
            for(auto y : a[x]) if(stay[y])
            {
                if(--ind[y] < least[y])
                {
                    sta[++top] = y;
                    stay[y] = 0;
                }
            }
        }

        puts(stay[ME] ? "stay" : "leave");
	}

	return 0;
}
/*
【trick&&吐槽】


【题意】


【分析】


【时间复杂度&&优化】
4 3 4 1
2 3
2 4
1 2

5 5 1 1
3 4
1 2
2 3
1 3
2 5

4 5 3 1
1 2
1 3
2 3
2 4
3 4

10 14 1 10
1 2
1 3
1 4
2 5
3 5
4 5
5 6
5 7
5 8
5 9
6 10
7 10
8 10
9 10

*/

  

D. Bridge Automation

设$f[i]$表示前$i$艘船开走的最小代价,枚举与$i$最早一起开走的船$j$转移即可。

时间复杂度$O(n^2)$。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 4040, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n;
int t[N];
int f[N];
int main()
{
	while(~scanf("%d", &n))
	{
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d", &t[i]);
        }

        MS(f, 63); f[1] = 0;
        for(int i = 1; i <= n; ++i)
        {
            //printf("%d\n", f[i]);
            int down = t[i] + 1800 - 60;            //桥放下的时间是定的
            int pre = t[i] + 1800 - 20;
            for(int j = i; j <= n; ++j)             //[i, j]一起走
            {
                pre = max(pre + 20, t[j]);          //这艘船开始开走的最早时间
                gmin(f[j + 1], f[i] + pre + 20 + 60 - down);
            }
        }
        printf("%d\n", f[n + 1]);
	}

	return 0;
}
/*
【trick&&吐槽】


【题意】


【分析】


【时间复杂度&&优化】

2
100
200

3
100
200
2010

3
100
200
2100

*/

  

E. Charles in Charge

二分答案,最短路检验。

时间复杂度$O(n\log^2n)$。

#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef pair<ll,int>P;
const int N=10010,M=200010;
const ll inf=1LL<<50;
int n,m,rate,i,x,y,z,g[N],v[M],w[M],nxt[M],ed,l,r,mid,ans;
ll mindis,d[N];
inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
ll dij(int lim){
    int i;
    for(i=1;i<=n;i++)d[i]=inf;
    priority_queue<P,vector<P>,greater<P> >q;
    q.push(P(d[1]=0,1));
    while(!q.empty()){
        P t=q.top();q.pop();
        if(d[t.second]>t.first)continue;
        for(i=g[t.second];i;i=nxt[i])if(w[i]<=lim&&d[v[i]]>t.first+w[i])
            q.push(P(d[v[i]]=t.first+w[i],v[i]));
    }
    return d[n];
}
int main(){
    scanf("%d%d%d",&n,&m,&rate);
    rate+=100;
    for(i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z),add(y,x,z);
    }
    mindis=dij(1000000000);
    mindis*=rate;
    //should / 100
    l=1,r=1000000000;
    while(l<=r){
        mid=(l+r)>>1;
        if(dij(mid)*100<=mindis)r=(ans=mid)-1;else l=mid+1;
    }
    printf("%d",ans);
}

  

F. Endless Turning

模拟$30000$步,这其中必然存在循环节,找出循环节后最后零碎部分继续模拟即可。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps=1e-9;
const int N=110;
const int inf=100000000;
long long T;
int n,m,i,pos,nxtpos;
char name[N][N];
int loop=inf;
inline int sgn(double x){
    if(x<-eps)return -1;
    if(x>eps)return 1;
    return 0;
}
struct P{
    double x,y;
    P(){x=y=0;}
    P(double _x,double _y){x=_x,y=_y;}
    P operator+(P b){return P(x+b.x,y+b.y);}
    P operator-(P b){return P(x-b.x,y-b.y);}
    P operator*(double b){return P(x*b,y*b);}
    P operator/(double b){return P(x/b,y/b);}
    bool operator==(P b){return !sgn(x-b.x)&&!sgn(y-b.y);}
    bool operator!=(P b){return sgn(x-b.x)||sgn(y-b.y);}
    bool operator<(P b){
        if(sgn(x-b.x))return x<b.x;
        return y<b.y;
    }
    double operator*(P v){return x*v.x+y*v.y;}
    double len(){return hypot(x,y);}
    double len_sqr(){return x*x+y*y;}
}A,B,C,D,a[N],b[N];
struct E{
    P x;
    int y,z;
    E(){}
    E(P _x,int _y,int _z){x=_x,y=_y,z=_z;}
}e[100010];
inline bool cmp(E a,E b){
    if(a.x!=b.x)return a.x<b.x;
    return a.y!=b.y?a.y<b.y:a.z<b.z;
}
inline double cross(P a,P b){return a.x*b.y-a.y*b.x;}
inline bool point_on_segment(P p,P a,P b){
    return sgn(cross(b-a,p-a))==0;
}
inline int line_intersection(P a,P b,P p,P q,P&o,double&t){
    double U=cross(p-a,q-p);
    double D=cross(b-a,q-p);
    if(sgn(D)==0)return 0;
    o=a+(b-a)*(U/D);
    t=U/D;
    return 1;
}
int getpos(P o){
    for(int i=1;i<=n;i++)if(point_on_segment(o,a[i],b[i]))return i;
    return 0;
}
inline bool go(){
    int nxt=0;double dis=1e100;
    for(int i=1;i<=n;i++)if(i!=abs(pos)){
        P o;double t;
        if(line_intersection(A,A+B,a[i],b[i],o,t)){
            //printf("->%d %.8f %.8f %.8f\n",i,o.x,o.y,t);
            if(t<eps)continue;
            if(t<dis)dis=t,nxt=i;
        }
    }
    if(!nxt)return 0;
    line_intersection(A,A+B,a[nxt],b[nxt],C,dis);
    nxtpos=nxt;
    D=b[nxt]-a[nxt];
    if(cross(C-A,C+D-A)>=0)nxtpos*=-1,D=D*(-1);
    return 1;
}
int main(){
    scanf("%d%lld%lf%lf",&n,&T,&A.x,&A.y);
    for(i=1;i<=n;i++){
        scanf("%s",name[i]);
        scanf("%lf%lf%lf%lf",&a[i].x,&a[i].y,&b[i].x,&b[i].y);
    }
    pos=getpos(A);
    
    if(T==0){
        puts(name[abs(pos)]);
        return 0;
    }
    
    B=b[pos]-a[pos];//direction
    if(B.x<0)B=B*(-1),pos*=-1;
    //printf("st : (%.8f,%.8f)->(%.8f,%.8f)\n",A.x,A.y,A.x+B.x,A.y+B.y);
    while(T>0&&m<30000){
        if(!go()){
            puts(name[abs(pos)]);
            return 0;
        }
        A=C,B=D,pos=nxtpos;
        //printf("(%.8f,%.8f)->(%.8f,%.8f)\n",A.x,A.y,A.x+B.x,A.y+B.y);
        T--;
        m++;
        e[m]=E(A,pos,m);
    }
    if(T==0){
        puts(name[abs(pos)]);
        return 0;
    }
    sort(e+1,e+m+1,cmp);
    
    for(i=1;i<m;i++)if(e[i].x==e[i+1].x&&e[i].y==e[i+1].y){
        loop=min(loop,e[i+1].z-e[i].z);
    }
    T%=loop;
    //printf("loop=%d\n",loop);
    while(T>0){
        go();
        A=C,B=D,pos=nxtpos;
        //printf("(%.8f,%.8f)->(%.8f,%.8f)\n",A.x,A.y,A.x+B.x,A.y+B.y);
        T--;
    }
    puts(name[abs(pos)]);
    
}
/*
3 4 1 1
Broadway 0 0 0 1
Narrowlane 0 0 1 0
Homedrive 1 1 2 0

3 4 5 0
Broadway 0 0 0 1
Narrowlane 0 0 1 0
Homedrive 1 1 2 0
*/

  

G. Manhattan Positioning System

将曼哈顿距离转切比雪夫距离,则可行解位于若干个正方形的交集上。

在对应正方形四个端点附近枚举所有点检查即可。

时间复杂度$O(n)$。

#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<set>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const ll inf=1LL<<60;
int n,i;
ll a[1010][3],xl,xr,yl,yr;
ll retx,rety;
set<P>ans;
inline void check(ll X,ll Y){
    ll x=(X+Y)/2,y=X-x;
    for(int i=1;i<=n;i++)if(abs(x-a[i][0])+abs(y-a[i][1])!=a[i][2])return;
    retx=x,rety=y;
    ans.insert(P(x,y));
}
void go(ll x,ll y){
    ll k=10;
    for(ll i=x-k;i<=x+k;i++)for(ll j=y-k;j<=y+k;j++)check(i,j);
}
int main(){
    scanf("%d",&n);
    xl=-inf;
    xr=inf;
    yl=-inf;
    yr=inf;
    for(i=1;i<=n;i++){
        ll x,y,d;
        scanf("%lld%lld%lld",&x,&y,&d);
        a[i][0]=x;
        a[i][1]=y;
        a[i][2]=d;
        ll X=x+y,Y=x-y;
        xl=max(xl,X-d);
        xr=min(xr,X+d);
        yl=max(yl,Y-d);
        yr=min(yr,Y+d);
    }
    go(xl,yl);
    go(xl,yr);
    go(xr,yl);
    go(xr,yr);
    if(ans.size()==0)puts("impossible");
    else if(ans.size()==1)printf("%lld %lld",retx,rety);
    else puts("uncertain");
}

  

H. Multiplying Digits

最优解中从低位到高位每个数必定是不上升的,爆搜剪枝配合卡时即可通过。

#include<cstdio>
#include<time.h>
typedef unsigned long long ll;
const int N = 11111;
const ll inf = 1ULL << 63;
ll K, n, i, a[N], ans = inf;
int m;
inline ll mul(ll a, ll b) {
	if (a>ans / b)return ans;
	return a*b;
}
int ED = 5.9 * CLOCKS_PER_SEC;
inline bool cal(ll ret, ll x, ll base, ll now) 
{
	while (ret >= x) 
	{
		now += mul(base, x);
		base = mul(base, K);
		if (now >= ans)return 0;
		ret /= x;
	}
	return 1;
}
void dfs(int x, ll base, ll ret, ll n) {//now consider a[x]
										//printf("%d %llu %llu %llu\n",x,base,ret,n);
	if (ret >= ans)return;
	if (clock() > ED)return;

	if (n == 1) {
		//printf("%llu\n",ret);
		ans = ret;
		return;
	}
	if (base >= ans)return;
	while (1) 
	{
		while (x <= m&&n%a[x])x++;
		if (x>m)return;

		ll t = ret + mul(base, a[x]);
		if (t >= ans)return;

		if (!cal(n, a[x], base, ret))return;

		dfs(x, mul(base, K), t, n / a[x]);
		if (clock() > ED)return;
		x++;
	}
}
int main() {
	/* ll t=1;
	for(i=1;i<=18;i++)t*=6;
	printf("%llu\n",t);*/
	scanf("%llu%llu", &K, &n);
	if (n == 1) {
		puts("1");
		return 0;
	}
	for (i = K - 1; i >= 2; i--)if (n%i == 0) {
		a[++m] = i;
	}
	//for(i=1;i<=m;i++)printf("%llu ",a[i]);puts("");
	//printf("%d\n",m);
	a[0] = a[m + 1] = 1;
	dfs(1, 1, 0, n);
	if (ans == inf)puts("impossible");
	else printf("%llu", ans);
	return 0;
}
/*
10 24

10 11

9 216

10000 5810859769934419200

9 101559956668416
*/

  

I. Older Brother

按题意模拟即可。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 0, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n;
bool solve()
{
    if(n == 1)return 0;
    for(int i = 2; i * i <= n; ++i)if(n % i == 0)
    {
        int x = n;
        while(x % i == 0)
        {
            x /= i;
        }
        return x == 1;
    }
    return 1;
}
int main()
{
	while(~scanf("%d", &n))
	{
        puts(solve() ? "yes" : "no");
	}

	return 0;
}
/*
【trick&&吐槽】


【题意】


【分析】


【时间复杂度&&优化】


*/

  

J. Programming Tutors

二分答案,二分图匹配检验。

时间复杂度$O(n^3\log n)$。

#include<cstdio>
const int N=110;
int n,i,j,l,r,mid,ans,d[N][N],v[N],f[N];
struct P{int x,y;}a[N],b[N];
inline int abs(int x){return x>0?x:-x;}
bool find(int x){
    for(int i=1;i<=n;i++)if(d[x][i]<=mid&&!v[i]){
        v[i]=1;
        if(!f[i]||find(f[i]))return f[i]=x,1;
    }
    return 0;
}
bool check(){
    int i,j;
    for(j=1;j<=n;j++)f[j]=0;
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++)v[j]=0;
        if(!find(i))return 0;
    }
    return 1;
}
int main(){
    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
    for(i=1;i<=n;i++)scanf("%d%d",&b[i].x,&b[i].y);
    for(i=1;i<=n;i++)for(j=1;j<=n;j++)d[i][j]=abs(a[i].x-b[j].x)+abs(a[i].y-b[j].y);
    l=0,r=1000000000;
    while(l<=r){
        mid=(l+r)>>1;
        if(check())r=(ans=mid)-1;else l=mid+1;
    }
    printf("%d",ans);
}

  

K. Safe Racing

设$f[i]$表示长度为$i$的序列,$1$和$i$必选时的合法方案数,可以通过前缀和$O(n)$求出。

枚举第一个放的位置,那么最后一个位置的范围是一个区间,同样可以前缀和加速。

时间复杂度$O(n)$。

#include<cstdio>
const int N=1000010,P=123456789;
int n,m,i,j,ans,f[N],s[N];
int main(){
    scanf("%d%d",&n,&m);
    f[1]=s[1]=1;
    for(i=2;i<=n;i++){
        f[i]=s[i-1];
        if(i-m-1>=0)f[i]-=s[i-m-1];
        f[i]=(f[i]+P)%P;
        s[i]=(s[i-1]+f[i])%P;
    }
    for(i=1;i<=m;i++){
        j=n-m+i;
        if(j>n)continue;
        int l=j-i+1,r=n-i+1;
        ans=(ans+s[r])%P;
        ans=(ans-s[l-1]+P)%P;
    }
    printf("%d",ans);
}

  

L. Sticky Situation

排序后检查相邻$3$项能否形成三角形即可。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 2e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n;
LL a[N];
bool solve()
{
    for(int i = 1; i <= n - 2; ++i)
    {
        if(a[i] + a[i + 1] > a[i + 2])return 1;
    }
    return 0;
}
int main()
{
	while(~scanf("%d", &n))
	{
        for(int i = 1; i <= n; ++i)
        {
            scanf("%lld", &a[i]);
        }
        sort(a + 1, a + n + 1);
        puts(solve() ? "possible" : "impossible");
	}

	return 0;
}
/*
【trick&&吐槽】


【题意】


【分析】


【时间复杂度&&优化】


*/

  

posted @ 2017-09-14 02:01  Claris  阅读(837)  评论(0编辑  收藏  举报