• [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
    ",1LL*p[i]*t[i]);
        return 0;
    }
  • 相关阅读:
    OC动态特性
    app之间的互相跳转
    将服务器返回的URL或者网址截取出来特定的字符,然后将字符返回,一般根据返回的字符判断用户是否登录等即时状态
    网络请求的封装
    代理传值
    sql脚本查询日期时间段日期
    SQL >日期函数
    Sql 中text类型字段判断是否为空
    修复IE9.0下PlaceHolder 属性问题js脚本
    迅雷专用下载的几种代码
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj2827.html
Copyright © 2020-2023  润新知