BZOJ 2500 幸福的道路(race) 树上直径+平衡树

structHeal
{
    priority_queue<int> real;
    priority_queue<int> stack;
    void push(int x){
        real.push(x);
    }
    void pop(int x){
        stack.push(x);
    }
    int top(){
        while(real.empty()==0&&stack.empty()==0&&real.top()==stack.top())
         real.pop(),stack.pop();
        if(real.empty())return0;
        return real.top();
    }
}

 

这样打堆虽然方便但是top到最后大约有6,7的常数。

今天考试卡常卡的怀疑人生……..这个故事告诉我们千万不要忘了常数分析..........

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<ctime>
#include<iostream>
#define MAXN 1000010
using namespace std;
inline int read()
{
    int sum=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')
    {
        sum=(sum<<1)+(sum<<3)+ch-'0';
        ch=getchar();
    }
    return sum;
}
struct ScapeGoat_Tree
{
    struct node
    {
       node *ch[2];
       int key,size,cover,ex;
       void update()
       {
         size=ch[0]->size+ch[1]->size+ex;
         cover=ch[0]->cover+ch[1]->cover+1;
       }
       bool bad()
       {
         return ch[0]->cover>=cover*0.756+5||ch[1]->cover>=cover*0.756+5;
       }
    }Mem[MAXN],*null,*root,*stack[MAXN],*lst[MAXN];
    int len,top;
    void Init()
    {
       root=null=Mem;
       null->size=null->cover=null->ex=0;
       null->ch[0]=null->ch[1]=Mem;
       for(int i=1;i<MAXN;i++)stack[++top]=Mem+i;
    }
    node *New(int key)
    {
       node *t=stack[top--];
       t->ch[0]=t->ch[1]=null;
       t->size=t->cover=t->ex=1;
       t->key=key;
       return t;
    }
    void travel(node *p)
    {
       if(p==null)return;
       travel(p->ch[0]);
       if(p->ex)lst[++len]=p;
       else stack[++top]=p;
       travel(p->ch[1]);
    }
    node *divide(int l,int r)
    {
        if(l>r)return null;
        int mid=(l+r)>>1;
        lst[mid]->ch[0]=divide(l,mid-1);
        lst[mid]->ch[1]=divide(mid+1,r);
        lst[mid]->update();
        return lst[mid];
    }
    void rebuild(node *&p)
    {
        len=0;
        travel(p);
        p=divide(1,len);
    }
    node **insert(node *&p,int key)
    {
        if(p==null)
        {
            p=New(key);
            return &null;
        }
        p->size++;
        p->cover++;
        node **ret=insert(p->ch[p->key<=key],key);
        if(p->bad())ret=&p;
        return ret;
    }
    void erace(node *p,int k)
    {
        p->size--;
        if(p->ex&&k==p->ch[0]->size+1)
        {
            p->ex=0;
            return;
        }
        if(k<=p->ch[0]->size)erace(p->ch[0],k);
        else erace(p->ch[1],k-p->ch[0]->size-p->ex);
    }
    int Kth(int k)
    {
        node *p=root;
        while(p!=null)
        {
            if(p->ex&&k==p->ch[0]->size+1)return p->key;
            else if(p->ch[0]->size>=k)p=p->ch[0];
            else k-=p->ch[0]->size+p->ex,p=p->ch[1];
        }
    }
    int Rank(int x)
    {
        node *p=root;
        int ret=1;
        while(p!=null)
        if(p->key>=x)
            p=p->ch[0];
        else
            ret+=p->ch[0]->size+p->ex,p=p->ch[1];
        return ret;
    }      
    void Insert(int x)
    {
        node **p=insert(root,x);
        if(*p!=null)rebuild(*p);
    }
    void Erace_kth(int k)
    {
        erace(root,k);
        if(root->size<root->cover*0.756)rebuild(root);
    }
    void Erace(int x)
    {
        Erace_kth(Rank(x));
    }
}YY;
inline int Max(int x,int y)
{
    return x>y?x:y;
}
inline int Abs(int x)
{
    return x<0?0-x:x;
}
int n,m;
struct Tr
{
    int to,next,w;
}c[MAXN<<1];
int head[MAXN],t;
int f[MAXN];
inline void add(int x,int y,int z)
{
    c[++t].to=y;
    c[t].w=z;
    c[t].next=head[x];
    head[x]=t;
}
int A[MAXN];
bool mark[MAXN];
int q[MAXN],top,tail,one,two;
inline void bfs1()
{
    memset(mark,0,sizeof(mark));
    memset(A,0,sizeof(A));
    q[1]=1;
    top=tail=1;
    int now=0;
    one=1;
    mark[1]=1;
    while(top<=tail)
    {
        int x=q[top++];
        if(A[x]>now)
        {
            one=x;
            now=A[x];
        }
        for(int i=head[x];i;i=c[i].next)
        if(mark[c[i].to]==0)
        {
            mark[c[i].to]=1;
            q[++tail]=c[i].to;
            A[c[i].to]=A[x]+c[i].w;
        }
    }
}
inline void bfs2()
{
    memset(mark,0,sizeof(mark));
    memset(A,0,sizeof(A));
    q[1]=one;
    top=tail=1;
    int now=0;
    two=one;
    mark[one]=1;
    while(top<=tail)
    {
        int x=q[top++];
        if(A[x]>now)
        {
            two=x;
            now=A[x];
        }
        for(int i=head[x];i;i=c[i].next)
        if(mark[c[i].to]==0)
        {
            mark[c[i].to]=1;
            q[++tail]=c[i].to;
            A[c[i].to]=A[x]+c[i].w;
        }
    }
}
inline void bfs3()
{
    memset(mark,0,sizeof(mark));
    memset(A,0,sizeof(A));
    q[1]=one;
    top=tail=1;
    mark[one]=1;
    while(top<=tail)
    {
        int x=q[top++];
        for(int i=head[x];i;i=c[i].next)
        if(mark[c[i].to]==0)
        {
            mark[c[i].to]=1;
            q[++tail]=c[i].to;
            A[c[i].to]=A[x]+c[i].w;
        }
    }
}
int B[MAXN];
inline void bfs4()
{
    memset(mark,0,sizeof(mark));
    q[1]=two;
    top=tail=1;
    mark[two]=1;
    while(top<=tail)
    {
        int x=q[top++];
        for(int i=head[x];i;i=c[i].next)
        if(mark[c[i].to]==0)
        {
            mark[c[i].to]=1;
            q[++tail]=c[i].to;
            B[c[i].to]=B[x]+c[i].w;
        }
    }
}
inline void Init()
{
    n=read(),m=read();
    m=Abs(m);
    YY.Init();
    for(int i=2;i<=n;i++)
    {
        int x=read(),y=read();
        add(x,i,y);
        add(i,x,y);
    }
    bfs1(),bfs2(),bfs3(),bfs4();
    for(int i=1;i<=n;i++)A[i]=Max(A[i],B[i]);
}
inline bool jud(int p)
{
    int x=YY.Kth(1),y=YY.Kth(YY.root->size);
    if(Abs(x-p)>m||Abs(y-p)>m)return 0;
    return 1;
}
inline void work()
{
    top=1;
    int ans=1;
    YY.Insert(A[1]);
    for(int i=2;i<=n;i++)
    {
        while(top!=i&&!jud(A[i]))
         YY.Erace(A[top]),top++;
        YY.Insert(A[i]);
        ans=Max(ans,YY.root->size);
    }
    printf("%d",ans);
}
int main()
{
    //freopen("race.in","r",stdin);
    //freopen("race.out","w",stdout);
    Init();
    work();
    return 0;
}

 

posted @ 2017-07-14 19:52  TS_Hugh  阅读(205)  评论(0编辑  收藏  举报