题目描述
输入
输出
样例输入
7
6 6 2 2 1
5 3 5 1 4
样例输出
TAK
1 5 2
5 7 1
5 2 4
7 3 3
1 4 2
1 6 1
题解
构造
考虑两种情况:
(1) $1$ 号点与 $n$ 号点直接相连
此时需要满足:对于所有的 $i$ ,$|d(1,i)-d(n,i)|$ 均相等。
满足此条件时容易构造出解: $1$ 号点与 $n$ 号点的边长度为 $|d(1,i)-d(n,i)|$ ;对于第 $i$ 个点,如果 $d(1,i)<d(n,i)$ 则与 $1$ 相连,长度为 $d(1,i)$ ;否则与 $n$ 相连,长度为 $d(n,i)$ 。
(2) $1$ 号点与 $n$ 号点不直接相连
此时 $1$ 号点与 $n$ 号点的距离为 $min\{dis(1,i)+dis(n,i)\}$ 。
设这个距离为 $d$ ,那么对于所有的 $dis(1,i)+dis(n,i)=d$ 的点 $i$(包括 $1$ 号点和 $n$ 号点),将其按照 $dis(1,i)$ 从小到大排序,则它们形成了一条从 $1$ 到 $n$ 的链。此时需要满足:这条链上的任意两个点的位置(即 $dis(1,i)$ )均不同。
然后考虑其它点:对于点 $x$ ,它到 $1$ 号点的方式一定是:先到达链上的某个点,然后再沿着链到 $1$ 。到 $n$ 同理。于是可以算出其到链上某个点的距离 $\frac {dis(1,x)+dis(n,x)-d}2$ ,进而得到 $1$ 到这个链上点的距离。此时需要满足: $dis(1,x)+dis(n,x)-d$ 为偶数,且 $|dis(1,x)-dis(n,x)|\le d$ ,且存在某个链上的点与 $1$ 的距离为 $dis(1,x)-\frac {dis(1,x)+dis(n,x)-d}2$ 。
满足这些条件时容易构造出解: $1$ 号点与 $n$ 号点的链之间的相邻两点 $a$ 和 $b$($a$ 比 $b$ 更靠近 $1$)连边,长度为 $dis(1,b)-dis(1,a)$ ,其余点向着链上对应的点连边,长度为 $\frac{dis(1,x)+dis(n,x)-d}2$ 。
查找对应点时可以使用二分查找解决。
这两种情况均不满足时无解。
时间复杂度 $O(n\log n)$
#include <cstdio>
#include <cctype>
#include <algorithm>
#define N 500010
using namespace std;
struct data
{
int d , p;
data() {}
data(int D , int P) {d = D , p = P;}
bool operator<(const data &a)const {return d < a.d;}
}v[N];
int a[N] , b[N] , l[N] , tot , x[N] , y[N] , z[N] , cnt;
int main()
{
int n , i , t , len = 1 << 30 , val;
scanf("%d" , &n);
if(n == 2)
{
puts("TAK\n1 2 1");
return 0;
}
for(i = 2 ; i < n ; i ++ ) scanf("%d" , &a[i]);
for(i = 2 ; i < n ; i ++ ) scanf("%d" , &b[i]) , l[i] = a[i] + b[i] , len = min(len , l[i]);
if(a[2] != b[2])
{
val = max(a[2] - b[2] , b[2] - a[2]);
for(i = 3 ; i < n ; i ++ )
if(a[i] - b[i] != val && b[i] - a[i] != val)
break;
if(i == n)
{
printf("TAK\n1 %d %d\n" , n , val);
for(i = 2 ; i < n ; i ++ )
{
if(a[i] < b[i]) printf("1 %d %d\n" , i , a[i]);
else printf("%d %d %d\n" , n , i , b[i]);
}
return 0;
}
}
v[++tot] = data(0 , 1);
for(i = 2 ; i < n ; i ++ )
if(l[i] == len)
v[++tot] = data(a[i] , i);
v[++tot] = data(len , n);
sort(v + 1 , v + tot + 1);
for(i = 1 ; i < tot ; i ++ )
{
if(v[i].d == v[i + 1].d)
{
puts("NIE");
return 0;
}
x[++cnt] = v[i].p , y[cnt] = v[i + 1].p , z[cnt] = v[i + 1].d - v[i].d;
}
for(i = 2 ; i < n ; i ++ )
{
if(l[i] != len)
{
if((l[i] - len) & 1 ||
(t = lower_bound(v + 1 , v + tot + 1 , data(a[i] - ((l[i] - len) >> 1) , 0)) - v) > tot ||
v[t].d != a[i] - ((l[i] - len) >> 1))
{
puts("NIE");
return 0;
}
x[++cnt] = v[t].p , y[cnt] = i , z[cnt] = (l[i] - len) >> 1;
}
}
puts("TAK");
for(i = 1 ; i <= cnt ; i ++ ) printf("%d %d %d\n" , x[i] , y[i] , z[i]);
return 0;
}