BZOJ2144 跳跳棋

蒟蒻只会广搜。。。20分。。。

后来发现对于一个状态,中间的一个棋子可以往两边跳,而两边的棋子最多只有一个可以往中间跳(怎么发现的?废话嘛、、、!)

故每个状态看做一个点,有关连的状态连起来,就形成了一棵二叉树

对于一个某个有解的状态而言,中间往两边跳的两个状态是它的儿子,两边往中间跳的状态是它的父亲

于是就变成了树上两点求距离问题。

暴力还是不行,只有40分。。。

hzwer:"我们发现若记前两个数差t1,后两个数差t2,不妨设t1<t2

则左边最多往中间跳(t2-1)/t1次

然后只能右边往中间跳,是一个辗转相除的过程,即在logK的时间内我们可以用这种方法得到某个结点它向上K次后的结点,或者根节点,同时还可以顺便算下深度"

好像挺对?Orz。。。

于是就变成了先把两个节点调到树上同一深度再二分LCA的深度即可,做完了。。。

 1 /**************************************************************
 2     Problem: 2144
 3     User: rausen
 4     Language: C++
 5     Result: Accepted
 6     Time:0 ms
 7     Memory:804 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <algorithm>
12  
13 using namespace std;
14 const int INF = (int) 1e9;
15 struct data{
16     int a[4];
17 };
18 inline bool operator != (const data a, const data b){
19     return a.a[1] != b.a[1] || a.a[2] != b.a[2] || a.a[3] != b.a[3];
20 }
21 int t1, t2, tmp, ans;
22 int a[4], b[4];
23  
24 data calc(int *a, int k){
25     data res;
26     int t1 = a[2] - a[1], t2 = a[3] - a[2], i, t;
27     for (i = 1; i < 4; ++i)
28         res.a[i] = a[i];
29     if (t1 == t2) return res;
30     if (t1 < t2){
31         t = min(k, (t2 - 1) / t1);
32         k -= t, tmp += t;
33         res.a[2] += t * t1, res.a[1] += t * t1;
34     }else{
35         t = min(k, (t1 - 1) / t2);
36         k -= t, tmp += t;
37         res.a[2] -= t * t2, res.a[3] -= t * t2;
38     }
39     return k ? calc(res.a, k) : res;
40 }
41  
42 int main(){
43     int d1, d2, i;
44     data t1, t2;
45     for (i = 1; i < 4; ++i)
46         scanf("%d", a + i);
47     for (i = 1; i < 4; ++i)
48         scanf("%d", b + i);
49     sort(a + 1, a + 4);
50     sort(b + 1, b + 4);
51     t1 = calc(a, INF), d1 = tmp, tmp = 0;
52     t2 = calc(b, INF), d2 = tmp, tmp = 0;
53     if (t1 != t2){
54         puts("NO");
55         return 0;
56     }
57     if (d1 > d2){
58         swap(d1, d2);
59         for (i = 1; i < 4; ++i)
60             swap(a[i], b[i]);
61     }
62     ans = d2 - d1;
63     t1 = calc(b, ans);
64     for (i = 1; i < 4; ++i)
65         b[i] = t1.a[i];
66     int l = 0, r = d1, mid;
67     while (l <= r){
68         mid = l + r >> 1;
69         if (calc(a, mid) != calc(b, mid)) l = mid + 1;
70         else r = mid - 1;
71     }
72     puts("YES");
73     printf("%d
", ans + 2 * l);
74     return 0;
75 }
View Code
By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
原文地址:https://www.cnblogs.com/rausen/p/4066457.html