码迷,mamicode.com
首页 > 其他好文 > 详细

AC日记——「HNOI2017」单旋 LiBreOJ 2018

时间:2017-06-28 23:22:09      阅读:272      评论:0      收藏:0      [点我收藏+]

标签:ret   turn   ext   xtree   minus   tag   lin   min   efi   

#2018. 「HNOI2017」单旋

 

思路:

  set+线段树;

 

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxn 100005
#define maxtree maxn<<2
int val[maxtree],tag[maxtree],L[maxtree],R[maxtree],mid[maxtree];
int op[maxn],ki[maxn],bi[maxn],cnt,size,n,ch[maxn][2],f[maxn],root;
set<int>Set;
inline void in(int &now)
{
    char Cget=getchar();now=0;
    while(Cget>9||Cget<0)Cget=getchar();
    while(Cget>=0&&Cget<=9)
    {
        now=now*10+Cget-0;
        Cget=getchar();
    }
}
void build(int now,int l,int r)
{
    L[now]=l,R[now]=r;if(l==r) return;mid[now]=l+r>>1;
    build(now<<1,l,mid[now]),build(now<<1|1,mid[now]+1,r);
}
inline void pushdown(int now)
{
    val[now<<1]+=tag[now],tag[now<<1]+=tag[now];
    val[now<<1|1]+=tag[now],tag[now<<1|1]+=tag[now];
    tag[now]=0;
}
void add(int now,int l,int r)
{
    if(L[now]>=l&&R[now]<=r)
    {
        val[now]++,tag[now]++;
        return;
    }
    if(tag[now]!=0) pushdown(now);
    if(l<=mid[now]) add(now<<1,l,r);
    if(r>mid[now]) add(now<<1|1,l,r);
}
void Minus(int now,int l,int r)
{
    if(L[now]>=l&&R[now]<=r)
    {
        val[now]--,tag[now]--;
        return;
    }
    if(tag[now]!=0) pushdown(now);
    if(l<=mid[now]) Minus(now<<1,l,r);
    if(r>mid[now]) Minus(now<<1|1,l,r);
}
int get(int to)
{
    int l=1,r=size,now=1;
    while(l!=r)
    {
        if(tag[now]!=0) pushdown(now);
        if(to<=mid[now]) r=mid[now],now=now<<1;
        else l=mid[now]+1,now=now<<1|1;
    }
    return val[now];
}
void era(int to,int justval)
{
    int l=1,r=size,now=1;
    while(l!=r)
    {
        if(tag[now]!=0) pushdown(now);
        if(to<=mid[now]) r=mid[now],now=now<<1;
        else l=mid[now]+1,now=now<<1|1;
    }
    val[now]=justval;
}
int main()
{
    freopen("data.txt","r",stdin);
    in(n);
    for(int i=1;i<=n;i++)
    {
        in(op[i]);
        if(op[i]==1) in(ki[i]),bi[++cnt]=ki[i];
    }
    sort(bi+1,bi+cnt+1),size=unique(bi+1,bi+cnt+1)-bi-1,build(1,1,size);
    int l,r,x,fa,cost;set<int>::iterator it,it_;
    for(int i=1;i<=n;i++)
    {
        if(op[i]==1)
        {
            x=lower_bound(bi+1,bi+size+1,ki[i])-bi;
            l=0,r=0,it=it_=Set.insert(x).first;
            if(it!=Set.begin()) l=*(--it);
            if(x!=*Set.rbegin()) r=*(++it_);
            if(!l&&!r) root=x,cost=1;
            else if(l&&ch[l][1]==0) ch[l][1]=x,f[x]=l,cost=get(l)+1;
            else if(r&&ch[r][0]==0) ch[r][0]=x,f[x]=r,cost=get(r)+1;
            printf("%d\n",cost),era(x,cost);
        }
        if(op[i]==2||op[i]==4)
        {
            it=Set.begin(),x=*it;
            if(x!=root)
            {
                printf("%d\n",get(x));
                if(ch[x][1]) Minus(1,x+1,f[x]-1),ch[f[x]][0]=ch[x][1],f[ch[x][1]]=f[x];
                else ch[f[x]][0]=0;
                ch[x][1]=root,f[root]=x,f[x]=0,root=x;
                add(1,1,size),era(x,1);
            }
            else printf("1\n");
            if(op[i]==4) root=ch[root][1],f[root]=0,Minus(1,1,size),Set.erase(it);
        }
        if(op[i]==3||op[i]==5)
        {
            it=Set.end(),x=*(--it);
            if(x!=root)
            {
                printf("%d\n",get(x));
                if(ch[x][0]) Minus(1,f[x]+1,x-1),ch[f[x]][1]=ch[x][0],f[ch[x][0]]=f[x];
                else ch[f[x]][1]=0;
                ch[x][0]=root,f[root]=x,f[x]=0,root=x;
                add(1,1,size),era(x,1);
            }
            else printf("1\n");
            if(op[i]==5) root=ch[root][0],f[root]=0,Minus(1,1,size),Set.erase(it);
        }
    }
    return 0;
}

 

AC日记——「HNOI2017」单旋 LiBreOJ 2018

标签:ret   turn   ext   xtree   minus   tag   lin   min   efi   

原文地址:http://www.cnblogs.com/IUUUUUUUskyyy/p/7091658.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!