ceoi 2011 treasure hunt

wc上第一次听这个题就感觉很有想法,于是想了个倍增,只能过50分,后来周而进讲了分块存图的方法,可惜只能用动态树维护,经ATM启发,每次分块后都不裂块,以适应倍增的树形态不变的性质,也就是后来钟沛林讲的方法,实现起来还比较容易,只是细节难以处理。

每个块我只存块状树深度,左右端点,每要处理一个点,二分其所处的块,倍增存2^k步的块,2^k步的点,2^k到块顶的距离,然后各种特判维护实际距离。

#include 
#include 
#include 
#include 
struct block
{
    int d,l,r;
}st[500000];
int ss,num,f[500000][30],g[500000][30],c[500000][30],a2[30],dis1,dis2,ans;
void init()
{
    int i,k;
    st[ss=1].d=0,st[1].l=1,st[1].r=1,num=1;
    for (i=1,k=29,a2[0]=1;i<=k;a2[i]=a2[i-1]*2,i++) ;
}
int search(int x)
{
    int l=1,r=ss,mid;
    for (;l<=r;)
    {
        mid=(l+r)>>1;
        if (st[mid].r=st[aa].l) return (a-d);
    e-=a-st[aa].l,ia=st[aa].l;
    for (k=0;e>0;)
    {
        if ((e-c[aa][k]>=0)&&(c[aa][k]!=0)) e-=c[aa][k],ia=g[aa][k],aa=f[aa][k],k++;
        else {
                if (0==k) e-=c[aa][k],ia=g[aa][k],aa=f[aa][k],k++;
                else k--;
            }
    }
    e+=ia-st[aa].l;return ia-e;
}
int min(int a,int b) {return (ab)&&((a+b)%2==1)) k++;return k;}
    if (st[aa].d>=1)
        if ((e&1)==1) dis1+=c[aa][k],ia=g[aa][k],aa=f[aa][k];    
    for (k=0;aa!=bb;)
    {
        if (f[aa][k]!=f[bb][k]) dis1+=c[aa][k],ia=g[aa][k],aa=f[aa][k],dis2+=c[bb][k],ib=g[bb][k],bb=f[bb][k],k++;
        else {
                    if (0==k) dis1+=c[aa][k],ia=g[aa][k],aa=f[aa][k],dis2+=c[bb][k],ib=g[bb][k],bb=f[bb][k],k++;
                    else k--;
            }
    }
    int flag=dis2;
    if (flag!=0)
        if (iaia) dis2+=b-ia;else dis1+=ia-b;
    if (dis1!=0) dis1-=(ia-st[aa].l);dis1+=a-st[ya].l;
    if (flag!=0) dis2-=(ib-st[aa].l),dis2+=b-st[yb].l;//else dis2=b-ia;
    if (0==flag) ib=b;    
    if (pd) e=ia,ia=ib,ib=e,e=dis1,dis1=dis2,dis2=e;    
    if (dis1==dis2) return min(ia,ib);
    if (dis1>dis2) return make(oa,(dis1+dis2)/2);
    else 
    {
        k=(dis1+dis2)/2;
        if (((dis1+dis2)&1)==1) k++;
        return make(ob,k);
    }
}


你可能感兴趣的:(图论,基本算法,ceoi)