BZOJ1143:[CTSC2008]祭祀river(&&BZOJ2718) 二分图
BZOJ1821:[JSOI2010]Group 部落划分 Group 二分+并查集

BZOJ2144:跳跳棋 LCA

shinbokuow posted @ Jan 29, 2015 09:37:24 PM in BZOJ with tags LCA , 1543 阅读

思路:

对于一个状态\((x,y,z)(x<y<z)\),我们发现可行的操作仅有三种:

(1)将\(y\)向左移动

(2)将\(y\)向右移动

(3)将\(x,z\)中离\(y\)比较近的一个以\(y\)为中心移动.(当\(y-x=z-y\)时不能这样做)

 

那么有人就要问了,还有离\(y\)比较远的以\(y\)为中心移动的情况呢?这必然与(1)(2)中的一个等价.

 

因此,我们可以将状态建成一棵树,对于一个状态,(1)(2)得到的是这个状态的左右儿子,(3)得到的是这个状态的父亲.

 

那么就很容易处理了.我们类似寻找LCA的过程不断向上爬即可.但我们不是暴力的向上找父亲,而是发现连续的若干次找父亲其实就是一个做gcd的过程.利用Euclid加速即可.

#include<cstdio>
#include<cstring>
#include<cctype>
#include<climits>
#include<iostream>
#include<algorithm>
using namespace std;
 
typedef long long LL;
 
struct Pos{
    int x,y,z;
    Pos(){}
    Pos(int _x,int _y,int _z):x(_x),y(_y),z(_z){}
    bool operator!=(const Pos&B)const{return x!=B.x||y!=B.y||z!=B.z;}
    bool operator==(const Pos&B)const{return x==B.x&&y==B.y&&z==B.z;}
};
 
LL updep;
inline Pos up(int x,int y,int z,LL d){
    if(d==0)return Pos(x,y,z);
    if(y-x==z-y)return Pos(x,y,z);
    int d1=y-x,d2=z-y,step;
    if(d1>d2){
        if(d1%d2==0){
            step=d1/d2-1;
            if(d<=step)return updep+=d,Pos(x,x+d1-d*d2,x+d1-d*d2+d2);
            else return updep+=step,up(x,x+d2,x+2*d2,d-step);
        }
        else{
            step=d1/d2;
            if(d<=step)return updep+=d,Pos(x,x+d1-d*d2,x+d1-d*d2+d2);
            else return updep+=step,up(x,x+d1%d2,x+d1%d2+d2,d-step);
        }
    }
    else{
        if(d2%d1==0){
            step=d2/d1-1;
            if(d<=step)return updep+=d,Pos(z-(d2-d*d1)-d1,z-(d2-d*d1),z);
            else return updep+=step,up(z-2*d1,z-d1,z,d-step);
        }
        else{
            step=d2/d1;
            if(d<=step)return updep+=d,Pos(z-(d2-d*d1)-d1,z-(d2-d*d1),z);
            else return updep+=step,up(z-d2%d1-d1,z-d2%d1,z,d-step);
        }
    }
}
inline Pos up(const Pos&p,LL d){return up(p.x,p.y,p.z,d);}
 
inline void Sort(int&x,int&y,int&z){
    int d[3]={x,y,z};sort(d,d+3);x=d[0],y=d[1],z=d[2];
}
 
int main(){
    int x1,y1,z1,x2,y2,z2;
    scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);Sort(x1,y1,z1),Sort(x2,y2,z2);
 
    LL dep1,dep2;
    updep=0;Pos Root1=up(x1,y1,z1,1<<30);dep1=updep;
    updep=0;Pos Root2=up(x2,y2,z2,1<<30);dep2=updep;
 
    if(Root1!=Root2)puts("NO");
    else{
        puts("YES");
        if(dep1<dep2)swap(dep1,dep2),swap(x1,x2),swap(y1,y2),swap(z1,z2);
        Pos now1=up(x1,y1,z1,dep1-dep2),now2=Pos(x2,y2,z2);
 
        if(now1==now2)printf("%d",dep1-dep2);
        else{
            int L=0,R=dep2,mid;
            while(L<R){
                mid=(L+R+1)>>1;
                if(up(now1,mid)!=up(now2,mid))L=mid;else R=mid-1;
            }
            printf("%d",dep1-dep2+2*(L+1));
        }
    }
#ifndef ONLINE_JUDGE
    system("pause");
#endif
 
    return 0;
}

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter