BZOJ5100 POI2018Plan metra(构造)

  容易发现要么1和n直接相连,要么两点距离即为所有dx,1+dx,n的最小值。若为前者,需要满足所有|d1-dn|都相等,挂两棵菊花即可。若为后者,将所有满足dx,1+dx,n=d1,n的挂成一条链,其余点直接与链上点相连即可,相连点需要满足dx,1-dx,n=dy,1-dy,n

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 500010
#define D 1000010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,a[N],b[N],id[D];
struct data
{
    int x,i;
    bool operator <(const data&a) const
    {
        return x<a.x;
    }
}d[N];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj5100.in","r",stdin);
    freopen("bzoj5100.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read();
    for (int i=2;i<n;i++) a[i]=read();
    for (int i=2;i<n;i++) b[i]=read();
    if (n==2) {cout<<"TAK\n"<<endl<<1<<' '<<2<<' '<<1;return 0;}
    int len=abs(a[2]-b[2]);
    for (int i=3;i<n;i++) if (abs(a[i]-b[i])!=len) {len=0;break;}
    if (len)
    {
        cout<<"TAK\n";
        cout<<1<<' '<<n<<' '<<len<<endl;
        for (int i=2;i<n;i++)
        if (a[i]>b[i]) printf("%d %d %d\n",i,n,b[i]);
        else printf("%d %d %d\n",i,1,a[i]);
        return 0;
    }
    len=2000000;
    for (int i=2;i<n;i++) len=min(len,a[i]+b[i]);
    int cnt=0;for (int i=2;i<n;i++) if (a[i]+b[i]==len) cnt++,d[cnt].x=a[i],d[cnt].i=i;
    sort(d+1,d+cnt+1);++cnt;d[0].x=0,d[0].i=1,d[cnt].x=len,d[cnt].i=n;
    for (int i=1;i<=cnt;i++) if (d[i].x==d[i-1].x) {cout<<"NIE";return 0;}
    for (int i=0;i<=cnt;i++) id[d[i].x]=d[i].i;
    for (int i=2;i<n;i++)
    if (a[i]+b[i]>len&&((a[i]+b[i]-len&1)||!id[a[i]-(a[i]+b[i]-len>>1)])) {cout<<"NIE";return 0;}
    cout<<"TAK\n";
    for (int i=1;i<=cnt;i++) printf("%d %d %d\n",d[i-1].i,d[i].i,d[i].x-d[i-1].x);
    for (int i=2;i<n;i++)
    if (a[i]+b[i]>len) printf("%d %d %d\n",id[a[i]-(a[i]+b[i]-len>>1)],i,a[i]+b[i]-len>>1);
    return 0;
}

 

posted @ 2018-12-06 20:46  Gloid  阅读(129)  评论(0编辑  收藏  举报