• bzoj2827: 千山鸟飞绝 平衡树 替罪羊树 蜜汁标记


    这道题首先可以看出坐标没有什么意义离散掉就好了。

    然后你就会发现你要每次都更改坐标,而一旦更改受影响的是坐标里的所有数,要是一个一个的改,会不可描述。

    所以换个视角,我们要找的是某只鸟所到每个坐标时遇到的最屌的鸟和遇到最大的团体,所以我就蒙了,这怎么改,蜜汁啊!

    蓝后就到了标记的神奇应用,用标记的下传重开来把每只鸟在每个坐标里所待的那段时间里遇到的收益搞到。

    两个标记: Max_army士气最大值 Max_one 团结最大值

       每次来了鸟先把那只鸟的威武值更新那个坐标再放他,放完他再打团结值最大值,关键。

       最后他走的时候把标记传给他,最最后输出之前先把每个点都更新。

       这样就完美了~~~

    我是用的替罪羊树来实现的这个蜜汁标记平衡树

    #include<cstdio>
    #include<cstring>
    #include<map>
    #include<iostream>
    #define MAXN 30005
    using namespace std;
    typedef double D;
    typedef unsigned long long ULL;
    typedef long long LL;
    const ULL K=233333333333333ULL;
    const D a=0.756;
    inline int Max(int x,int y)
    {
        return x>y?x:y;
    }
    int pos[MAXN];
    map<ULL,int>bird;
    int Max_army[MAXN],Max_one[MAXN],n,t,w[MAXN],sz;
    inline ULL hash(int x,int y)
    {
        if(x>=0&&y>=0)
          return (ULL)(x*K+y);
        if(x>=0&&y<0)
        {
            y=-y;
            return (ULL)(x*K-y);
        }
        if(x<0&&y>=0)
        {
            x=-x;
            return (ULL)(y-x*K);
        }
        if(x<0&&y<0)
        {
            x=-x;
            y=-y;
            return (ULL)(0-y-K*x);
        }
    }
    struct ScapeGoat_Tree
    {
        ScapeGoat_Tree *ch[2];
        int size,key,cover,ex,num,max_army,max_one;
        bool bad()
        {
            return cover*a+5<ch[0]->cover||cover*a+5<ch[1]->cover;
        }
        void pushup()
        {
            size=ch[1]->size+ch[0]->size+ex;
            cover=ch[1]->cover+ch[0]->cover+1;
        }
    }pool[MAXN<<2],*null,*stack[MAXN<<2],*lst[MAXN<<2],*root[MAXN<<4];
    int top,len;
    inline void pushdown(ScapeGoat_Tree *p)
    {
       if(p->ex)
       {
          Max_one[p->num]=Max(Max_one[p->num],p->max_one);
          Max_army[p->num]=Max(Max_army[p->num],p->max_army);
       }
       if(p->max_one)
       {
        if(p->ch[0]!=null)
          p->ch[0]->max_one=Max(p->ch[0]->max_one,p->max_one);
        if(p->ch[1]!=null)
          p->ch[1]->max_one=Max(p->ch[1]->max_one,p->max_one);
        p->max_one=0;
       }
       if(p->max_army)
       {
          if(p->ch[0]!=null)
            p->ch[0]->max_army=max(p->ch[0]->max_army,p->max_army);
          if(p->ch[1]!=null)
            p->ch[1]->max_army=max(p->ch[1]->max_army,p->max_army);
          p->max_army=0;
       }
    }
    inline void Init()
    {
        null=pool;
        null->size=null->key=null->ex=null->cover=null->num=null->max_army=null->max_one=0;
        null->ch[1]=null->ch[0]=null;
        for(int i=0;i<(MAXN<<4);i++) root[i]=null;
        for(int i=1;i<(MAXN<<2);i++) stack[++top]=pool+i;
    }
    inline ScapeGoat_Tree *New(int key,int i)
    {
        ScapeGoat_Tree *p;
        p=stack[top--];
        p->size=p->cover=p->ex=1;
        p->max_army=p->max_one=0;
        p->key=key;
        p->num=i;
        p->ch[1]=p->ch[0]=null;
        return p;
    }
    void travel(ScapeGoat_Tree *p)
    {
        if(p==null)return;
        pushdown(p);
        travel(p->ch[0]);
        if(p->ex)lst[++len]=p;
        else stack[++top]=p;
        travel(p->ch[1]);
    }
    ScapeGoat_Tree *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]->pushup();
        return lst[mid];
    }
    inline void rebuild(ScapeGoat_Tree *&p)
    {
        len=0;
        travel(p);
        p=divide(1,len);
    }
    ScapeGoat_Tree **insert(ScapeGoat_Tree *&p,int key,int i)
    {
        if(p==null)
        {
           p=New(key,i);
           return &null;
        }
        pushdown(p);
        p->size++;
        p->cover++;
        ScapeGoat_Tree **ret=insert(p->ch[p->key<=key],key,i);
        if(p->bad())ret=&p;
        return ret;
    }
    inline int Rank(ScapeGoat_Tree *Root,int k)
    {
        ScapeGoat_Tree *now=Root;
        while(now!=null)
         if(now->ex&&now->ch[1]->size+1==k) return now->key;
         else if(now->ch[1]->size>=k) now=now->ch[1];
         else k-=now->ch[1]->size+now->ex,now=now->ch[0];
        return 0;
    }
    inline int Kth(ScapeGoat_Tree *Root,int key)
    {
        ScapeGoat_Tree *now=Root;
        int ret=1;
        while(now!=null)
         if(now->key>=key)
          now=now->ch[0];
         else
          ret+=now->ch[0]->size+now->ex,now=now->ch[1];
        return ret;
    }
    inline void Insert(ScapeGoat_Tree *&Root,int key,int i)
    {
        Max_army[i]=Max(Max_army[i],Rank(Root,1));
        if(Root!=null)
           Root->max_army=Max(Root->max_army,key);
        ScapeGoat_Tree **p=insert(Root,key,i);
        if(*p!=null)rebuild(*p);
        Root->max_one=Max(Root->max_one,Root->size);
    }
    void Delete_Kth(ScapeGoat_Tree *p,int k)
    {
        pushdown(p);
        p->size--;
        if(p->ex&&p->ch[0]->size+1==k) 
        {
           p->ex=0;
           return;
        }
        if(p->ch[0]->size>=k) Delete_Kth(p->ch[0],k);
        else Delete_Kth(p->ch[1],k-p->ch[0]->size-p->ex);
    }
    inline void Delete(ScapeGoat_Tree *&Root,int key)
    {
        Delete_Kth(Root,Kth(Root,key));
        if(Root->size<Root->cover*a)rebuild(Root);
    }
    void dfs(ScapeGoat_Tree *p)
    {
         if(p==null)return;
         pushdown(p);
         dfs(p->ch[0]);
         dfs(p->ch[1]);
    }
    int main()
    {
        //freopen("bird.in","r",stdin);
        //freopen("bird.out","w",stdout);
        Init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int x,y;
            scanf("%d%d%d",&w[i],&x,&y);
            int p=bird[hash(x,y)];
            if(!p) p=bird[hash(x,y)]=++sz;
            pos[i]=p;
            Insert(root[p],w[i],i);
        }
        scanf("%d",&t);
        for(int i=1;i<=t;i++)
        {
            int v,x,y;
            scanf("%d%d%d",&v,&x,&y);
            int p=bird[hash(x,y)];
            if(!p) p=bird[hash(x,y)]=++sz;
            Delete(root[pos[v]],w[v]);
            pos[v]=p;
            Insert(root[p],w[v],v);
        }
        for(int i=1;i<=sz;i++)
         dfs(root[i]);
        for(int i=1;i<=n;i++)
        {
          LL ans=(LL)(Max_one[i]-1)*Max_army[i];
          printf("%lld
    ",ans);
        }
        return 0;
    }
    苟利国家生死以, 岂因祸福避趋之。
  • 相关阅读:
    关于JEE web项目 Servlet中 “/” 的解释 ;
    通过session 怎么防止表单的重复提交!
    Struts hibernate Spring 框架原理
    apache DBUtils 使用例子demo
    二十三种设计模式通俗理解
    怎样将一个脚本添加到开机自启动中
    zabbix
    数据库
    nginx服务器
    Luogu P3398 仓鼠找sugar
  • 原文地址:https://www.cnblogs.com/TSHugh/p/6994593.html
Copyright © 2020-2023  润新知