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;
}
苟利国家生死以, 岂因祸福避趋之。
原文地址:https://www.cnblogs.com/TSHugh/p/6994593.html