[bzoj2827]千山鸟飞绝

来自FallDream的博客,未经允许,请勿转载,谢谢。


 

话说有一天doyouloveme和vfleaking到山里玩。谁知doyouloveme刚刚进山,所有的鸟儿竟被他的神犇气场给惊得全部飞走了。vfleaking顿时膜拜不已。
这时鸟王用鸟语说道:“!@#$%……?”安抚了一下众鸟的情绪。鸟王生性好斗,作出了一个决定——要排鸟布阵把刚才吓到它们的人类赶出山去。
每只鸟都有一个编号,都有一个威武值。每秒钟鸟王都会发一个命令,编号为v的鸟飞到(x,y)去(坐标系原点是山顶,坐标单位为鸟爪)。鸟飞得很快,一秒之内就飞到了,可以看作是瞬间移动。如果编号为v的鸟和编号为u的鸟某一时刻处在同一位置,它们就会互相鼓励,增加各自的士气值和团结值。一只鸟的士气值等于此刻与它处在同一位置的鸟中的威武值的最大值,团结值等于此刻与它处在同一位置的鸟的只数。如果每一时刻都没有鸟与它处在同一位置,则士气值和团结值都为0。要注意自己不能鼓励自己,计算士气值和团结值时不能算上自己。
t秒钟后,doyouloveme目测出了现在每只鸟的战斗力,于是感叹了一句:“不妙,我们得走了。”
正所谓团结的鸟儿一个顶俩,所以doyouloveme这样描述战斗力:一只鸟战斗力值等于它在0到t秒中士气值的最大值与团结值的最大值的乘积。注意不是乘积的最大值,而是最大值的乘积。
vfleaking很想知道现在每只鸟的战斗力,但是他当然不会啦,于是他把这个任务交给了你来完成。
n<=30000 m<=300000
 
考虑对于每一个点维护所有在上面的鸟。
插入一只鸟的时候,先更新那只鸟的答案,然后给全部点打一个标记,最后插入。飞走的时候直接删除即可
选择平衡树来维护就行了。
因为这道题鸟没有顺序,所以我写了个奇妙的东西
复杂度mlogn
#include<iostream>
#include<cstdio>
#include<map>
#define mp(x,y) make_pair(x,y)
#define MN 350000
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}
map<pair<int,int>,int> mp;
int n,m,t[MN+5],s[MN+5],mx[MN+5],size[MN+5],cnt=0,p[MN+5],tag[MN+5];
int c[MN+5][2],fa[MN+5],q[MN+5],top=0,mark,Tag[MN+5],rt[MN+5]; 
pair<int,int> a[MN+5];
inline void AddTag(int x,int v){if(!Tag[x]||s[v]>s[Tag[x]]) Tag[x]=v;}
inline void Addtag(int x,int v){tag[x]=max(tag[x],v);}
inline void update(int x){size[x]=size[c[x][0]]+size[c[x][1]]+1;mx[x]=max(s[x],max(mx[c[x][0]],mx[c[x][1]]));}

void pushdown(int x)
{
    int l=c[x][0],r=c[x][1];
    if(Tag[x])
    {
        t[x]=max(t[x],s[Tag[x]]);
        if(l) AddTag(l,Tag[x]);
        if(r) AddTag(r,Tag[x]);
        Tag[x]=0;
    }
    if(tag[x])
    {
        p[x]=max(p[x],tag[x]);
        if(l) Addtag(l,tag[x]);
        if(r) Addtag(r,tag[x]);    
        tag[x]=0;
    }
}

void Ins(int&x,int v,int last)
{
    if(!x){x=v;size[x]=1;mx[x]=s[x];fa[x]=last;return;}
    pushdown(x);
    Ins(c[x][size[c[x][1]]<size[c[x][0]]],v,x);
    update(x);
}

int GetDown(int x)
{
    if(!x) return 0;pushdown(x);
    int y=GetDown(c[x][size[c[x][1]]>size[c[x][0]]]);
    return y?y:x;    
}

void Del(int from,int x)
{
    for(int t=x;t;t=fa[t]) q[++top]=t;
    for(;top;--top) pushdown(q[top]);
    int z;
    if(size[x]==1)
    {
        if(rt[from]==x) rt[from]=0;
        else c[fa[x]][c[fa[x]][1]==x]=0;
        z=fa[x];
    }
    else 
    {
        int y=GetDown(x);z=(fa[y]==x?y:fa[y]);
        if(rt[from]==x) rt[from]=y;
        else c[fa[x]][c[fa[x]][1]==x]=y;
        c[fa[y]][c[fa[y]][1]==y]=0;
        c[y][0]=c[x][0];c[y][1]=c[x][1];fa[y]=fa[x];
        fa[c[y][0]]=fa[c[y][1]]=y;
    }
    for(;z;z=fa[z]) update(z);
    c[x][0]=c[x][1]=fa[x]=0;
}

void Down(int x)
{
    if(!x) return;pushdown(x);
    Down(c[x][0]);
    Down(c[x][1]);    
}

int main()
{
    n=read();
    for(int i=1;i<=n;++i) 
    {
        s[i]=read();
        a[i].first=read();a[i].second=read();
        !mp[a[i]]?mp[a[i]]=++cnt:0;int ha=mp[a[i]];
        t[i]=max(t[i],mx[rt[ha]]);p[i]=max(p[i],size[rt[ha]]); 
        if(rt[ha])AddTag(rt[ha],i),Addtag(rt[ha],size[rt[ha]]);
        Ins(rt[ha],i,0);
    }
    m=read();
    for(int i=1;i<=m;++i)
    {
        int v=read(),x=read(),y=read();    
        Del(mp[a[v]],v);
        a[v]=mp(x,y);
        !mp[a[v]]?mp[a[v]]=++cnt:0;int ha=mp[a[v]];
        t[v]=max(t[v],mx[rt[ha]]);p[v]=max(p[v],size[rt[ha]]); 
        if(rt[ha])AddTag(rt[ha],v),Addtag(rt[ha],size[rt[ha]]);
        Ins(rt[ha],v,0); 
    }
    for(int i=1;i<=n;++i)
    {
        int v=rt[mp[a[i]]];
        if(v)Down(v);rt[mp[a[i]]]=0;    
    } 
    for(int i=1;i<=n;++i) printf("%lld\n",1LL*p[i]*t[i]);
    return 0;
}
posted @ 2017-06-29 16:27  FallDream  阅读(539)  评论(0编辑  收藏  举报