1. 程式人生 > >BZOJ 2500 幸福的道路(race) 樹上直徑+平衡樹

BZOJ 2500 幸福的道路(race) 樹上直徑+平衡樹

pri 平衡樹 efi fin eal add -- span names

structHeal

{

    priority_queue<int> real;

    priority_queue<int> stack;

    voidpush(int x)

    {

        real.push(x);

    }

    voidpop(int x)

    {

        stack.push(x);

    }

    inttop()

    {

        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; }

BZOJ 2500 幸福的道路(race) 樹上直徑+平衡樹