【BZOJ 2144】【JZOJ 4701】Throw

来源:互联网 发布:判断矩阵计算公式 编辑:程序博客网 时间:2024/06/01 19:08

Description

这里写图片描述

抽象题意:有3个点在数轴上移动,每次移动可以把a点绕b转到a’,并且符合a~a’中无它点。

Solution

把3个点的位置用一个3元组来表示,(x,y,z) ,满足x<y<z
(x,y,z)每轮的旋转有以下几种情况:
l=yxrzy
从里到外:
(x,y,z)~(xl,yl,z)
(x,y,z)~(x,yr,zr)
从外到里:
(x,y,z)~(x+l,y+l,z)l<r,
(x,y,z)~(x,yr,zr)l>r
我们发现,这就是一棵树,
以从外到里为根,每轮不停向上跳,求LCA即可,
然而会超时 ,
把式子转化一下:
当l>r时,用可能因差距巨大,要不停的把x转过去,
然而这没有必要,因为每轮只是r=r-l,
所有我们可以一次性把r减到减不了为止,这样可以大大的减小时间,(与求gcd是类似)
分别求出目标和当前的层数后,先把目标和当前快跳到同一层,再枚举一个2k,看看两个点向上跳这么多后相不相同,
复杂度:O(nlog(n))

Code

#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)#define FZA() a1=x,a2=y,a3=z#define FZB() b1=x,b2=y,b3=z#define OK() (q==x&&w==y&&e==z)using namespace std;typedef long long LL;const int N=100500,maxlongint=2147483640;int m,n,ans;int a1,a2,a3,b1,b2,b3,a0,b0;int x,y,z,s1,s2;int jump(int q,int w,int e){    int l=w-q,r=e-w,s=0;    x=q,y=w,z=e;    if(r>l)    {        s=r/l;        if(r%l)r=r%l;else s--,r=l;        y=z-r;x=y-l;        return s;    }    s=l/r;    if(l%r)l=l%r;else s--,l=r;    y=x+l;z=y+r;    return s;}void jumpo(int q,int w,int e){    int l=w-q,r=e-w;    x=q,y=w,z=e;    if(r>l)r=r-l,y=z-r,x=y-l;        else l=l-r,y=x+l,z=y+r;}void jumpt(int q,int w,int e,int s1,int s2){    int t;    while(s1>s2)    {        t=jump(q,w,e);        if(s1-t<s2)break;        q=x,w=y,e=z;        s1-=t;    }    x=q,y=w,z=e;    if(s1>s2)    {        s1=s1-s2;        int l=w-q,r=e-w;        if(r>l)r=r-l*s1,y=z-r,x=y-l;        else l=l-r*s1,y=x+l,z=y+r;    }}int main(){    int q,w,e,t;    scanf("%d%d%d%d%d%d",&a1,&a2,&a3,&b1,&b2,&b3);    if(a1>a2)swap(a1,a2);if(a1>a3)swap(a1,a3);if(a2>a3)swap(a2,a3);    if(b1>b2)swap(b1,b2);if(b1>b3)swap(b1,b3);if(b2>b3)swap(b2,b3);    x=a1,y=a2,z=a3;    while(y-x!=z-y)s1+=jump(x,y,z);    q=x,w=y,e=z;    x=b1,y=b2,z=b3;    while(y-x!=z-y)s2+=jump(x,y,z);    if(q!=x||w!=y||e!=z){printf("NO\n");return 0;}    if(!s1||!s2){printf("YES\n%d\n",s1+s2);return 0;}    ans+=abs(s1-s2);    jumpt(a1,a2,a3,s1,s2),FZA();    jumpt(b1,b2,b3,s2,s1),FZB();    s1=min(s1,s2);    t=1;    while(t*2<=s1)t<<=1;    while((a1!=b1||a2!=b2||a3!=b3)&&t)    {        while(s1<t)t/=2;        jumpt(a1,a2,a3,s1,s1-t);        q=x,w=y,e=z;        jumpt(b1,b2,b3,s1,s1-t);        if(!OK())        {            ans+=t*2;            s1-=t;            a1=q,a2=w,a3=e;            b1=x,b2=y,b3=z;        }        t/=2;    }    while(a1!=b1||a2!=b2||a3!=b3)jumpo(a1,a2,a3),FZA(),jumpo(b1,b2,b3),FZB(),ans+=2;    printf("YES\n%d\n",ans);    return 0;}
0 0
原创粉丝点击