这什么神题啊…
https://www.luogu.org/problemnew/show/P1852
想了一个小时一点儿思路也没(头里只有爆搜) 看了题解才知道是树…这谁顶的住啊
考虑中间点到两边距离相同的情况,此时显然已经不能往内部跳,只能向外部扩展,而可以证明的是,任意一种状态总能跳到这样一种状态(原理类似辗转相除),称为终态
这样的话,如果两个状态的终态不同,那么它们一定不能相互转化
如果二者终态相同,那么考虑不是终态的情况。显然只能有一种跳跃方式,因此每一个状态到终态的距离都是唯一的且可求的。我们把每一个状态看作点,所求就是始末态的lca
这个思路有了以后,就很好做了。二分距离K考虑跳完之后是否在同一状态即可
复杂度O(nlog^2n)
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; #define clr(a) memset(a,0,sizeof(a)) inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } struct node { int x,y,z; inline void sor() { if(x > y) swap(x,y); if(x > z) swap(x,z); if(y > z) swap(y,z); } }t1,t2,rt1,rt2,temp1,temp2; int find_root(node& b) { int stp = 0; b.sor(); while(b.x + b.z != 2 * b.y) { int d1 = b.y - b.x,d2 = b.z - b.y; if(d1 < d2) { int tp = d2 / d1; if(d2 % d1 == 0) tp--; b.x += tp * d1; b.y += tp * d1; b.sor(); stp += tp; } else { int tp = d1 / d2; if(d1 % d2 == 0) tp--; b.y -= tp * d2; b.z -= tp * d2; b.sor(); stp += tp; } } return stp; } bool same(node a,node b) { return a.x == b.x && a.y == b.y && a.z == b.z; } node get_pos(node b,int lim) { b.sor(); while(lim) { int d1 = b.y - b.x,d2 = b.z - b.y; if(d1 < d2) { int tp = d2 / d1; if(d2 % d1 == 0) tp--; tp = min(tp,lim); b.x += tp * d1; b.y += tp * d1; b.sor(); lim -= tp; } else { int tp = d1 / d2; if(d1 % d2 == 0) tp--; tp = min(tp,lim); b.y -= tp * d2; b.z -= tp * d2; b.sor(); lim -= tp; } } return b; } int st1,st2,ans; int main() { t1.x = read(),t1.y = read(),t1.z = read(); t2.x = read(),t2.y = read(),t2.z = read(); t1.sor();t2.sor(); rt1 = t1,rt2 = t2; st1 = find_root(rt1); st2 = find_root(rt2); if(!same(rt1,rt2)) { printf("NO"); return 0; } int st = abs(st1 -st2); if(st1 < st2) t2 = get_pos(t2,st); else t1 = get_pos(t1,st); int l = 0,r = min(st1,st2); while(l <= r) { int mid = l + r >> 1; temp1 = get_pos(t1,mid); temp2 = get_pos(t2,mid); if(same(temp1,temp2)) { ans = mid,r = mid - 1; } else l = mid + 1; } printf("YES %d",st + ans * 2); }