bzoj2827: 千山鸟飞绝

Description
话说有一天doyouloveme和vfleaking到山里玩。谁知doyouloveme刚刚进山,所有的鸟儿竟被他的神犇气场给惊得全部飞走了。vfleaking顿时膜拜不已。
这时鸟王用鸟语说道:“!@#$%……?”安抚了一下众鸟的情绪。鸟王生性好斗,作出了一个决定——要排鸟布阵把刚才吓到它们的人类赶出山去。
每只鸟都有一个编号,都有一个威武值。每秒钟鸟王都会发一个命令,编号为v的鸟飞到(x,y)去(坐标系原点是山顶,坐标单位为鸟爪)。鸟飞得很快,一秒之内就飞到了,可以看作是瞬间移动。如果编号为v的鸟和编号为u的鸟某一时刻处在同一位置,它们就会互相鼓励,增加各自的士气值和团结值。一只鸟的士气值等于此刻与它处在同一位置的鸟中的威武值的最大值,团结值等于此刻与它处在同一位置的鸟的只数。如果每一时刻都没有鸟与它处在同一位置,则士气值和团结值都为0。要注意自己不能鼓励自己,计算士气值和团结值时不能算上自己。
t秒钟后,doyouloveme目测出了现在每只鸟的战斗力,于是感叹了一句:“不妙,我们得走了。”
正所谓团结的鸟儿一个顶俩,所以doyouloveme这样描述战斗力:一只鸟战斗力值等于它在0到t秒中士气值的最大值与团结值的最大值的乘积。注意不是乘积的最大值,而是最大值的乘积。
vfleaking很想知道现在每只鸟的战斗力,但是他当然不会啦,于是他把这个任务交给了你来完成。
Input
第一行一个数n,代表鸟的只数。(鸟王那家伙你可以完全忽视掉)
接下来n行,每行三个整数w,x,y描述每只鸟的威武值和初始坐标。第i+1行描述编号为i的鸟。
接下来一行有一个数t,代表经过时间ts。
接下来t行,每行三个整数v,x,y描述鸟王每秒的命令。
Output
一共n行,每行一个数,代表每只鸟的战斗力。
对每只鸟建一个节点,每个坐标维护一颗平衡树,同时维护标记(区间最/次大值,size,全树最/次大值,size,单点历史最/次大值,历史最大size等),每个操作对应平衡树的插入和删除,处理完所有询问最后暴力下传所有标记即得到答案
#include<cstdio>
#include<cstdlib>
int _(){
    int x=0,c=getchar(),f=1;
    while(c<48)c=='-'&&(f=-1),c=getchar();
    while(c>47)x=x*10+c-48,c=getchar();
    return x*f;
}
const int P=621239;
int h[P][4];
int&get(int x,int y){
    int w=unsigned(x*1844677+y*293+141)%P;
    while(h[w][2]){
        if(h[w][0]==x&&h[w][1]==y)return h[w][3];
        if((w+=12347)>=P)w-=P;
    }
    h[w][0]=x;h[w][1]=y;h[w][2]=1;
    return h[w][3];
}
inline void maxs(int&a,int b){if(a<b)a=b;}
int n,q;
struct node{
    int rnd,v0,x,y,ch[2],m1,m2,m3,mt[3],as[3];
    void Ins();
    void Del();
    long long val(){
        return 1ll*(v0==as[0]?as[1]:as[0])*(as[2]-1);
    }
    void clr(){
        ch[0]=ch[1]=0;
        m1=v0;m2=0;m3=1;
        for(int i=0;i<3;++i)mt[i]=0;
    }
    void upd(){
        mt[0]=m1;mt[1]=m2;mt[2]=m3;
        for(int i=0;i<3;++i)maxs(as[i],mt[i]);
    }
}ns[30007];
inline void chk(int&a,int&b,int c){
    if(c>=a)b=a,a=c;
    else if(c>b)b=c;
}
inline void maxs(int&a,int&b,int c){
    if(a<c)a=c;
    if(b<c)b=c;
}
void dn(int w){
    for(int d=0,u;d<2;++d)if(u=ns[w].ch[d]){
        for(int j=0;j<3;++j)maxs(ns[u].mt[j],ns[u].as[j],ns[w].mt[j]);
    }
    for(int j=0;j<3;++j)ns[w].mt[j]=0;
}
void dns(int w){
    if(!w)return;
    dn(w);
    for(int d=0;d<2;++d)dns(ns[w].ch[d]);
}
void up(int w){
    ns[w].m1=ns[w].v0;ns[w].m2=0;ns[w].m3=1;
    for(int d=0,u;d<2;++d)if(u=ns[w].ch[d]){
        chk(ns[w].m1,ns[w].m2,ns[u].m1);
        chk(ns[w].m1,ns[w].m2,ns[u].m2);
        ns[w].m3+=ns[u].m3;
    }
}
void rot(int&w,int d){
    int u=ns[w].ch[d];
    dn(w);dn(u);
    ns[w].ch[d]=ns[u].ch[d^1];
    ns[u].ch[d^1]=w;
    up(w);up(u);
    w=u;
}
void ins(int&w,int x){
    if(!w){
        w=x;
        return;
    }
    dn(w);
    int d=w<x;
    ins(ns[w].ch[d],x);
    if(ns[ns[w].ch[d]].rnd>ns[w].rnd)rot(w,d);
    else up(w);
}
void dels(int&w){
    if(ns[w].ch[0]|ns[w].ch[1]){
        int d=ns[ns[w].ch[0]].rnd<ns[ns[w].ch[1]].rnd;
        rot(w,d);
        dels(ns[w].ch[d^1]);
        up(w);
    }else w=0;
}
void del(int&w,int x){
    if(w==x){
        dels(w);
        return;
    }
    dn(w);
    int d=w<x;
    del(ns[w].ch[d],x);
    if(ns[ns[w].ch[d]].rnd>ns[w].rnd)rot(w,d);
    else up(w);
}
void node::Ins(){
    clr();
    int&rt=get(x,y);
    ins(rt,this-ns);
    ns[rt].upd();
}
void node::Del(){
    int&rt=get(x,y);
    del(rt,this-ns);
    if(rt)ns[rt].upd();
    clr();
}
int main(){
    srand(29397);
    n=_();
    for(int i=1;i<=n;++i){
        ns[i].v0=_();
        ns[i].x=_();
        ns[i].y=_();
        ns[i].rnd=rand();
        ns[i].Ins();
    }
    for(q=_();q;--q){
        int i=_();
        ns[i].Del();
        ns[i].x=_();
        ns[i].y=_();
        ns[i].Ins();
    }
    for(int i=0;i<P;++i)dns(h[i][3]);
    for(int i=1;i<=n;++i)printf("%lldn",ns[i].val());
    return 0;
}
 

相关内容推荐