首页 > 其他分享 >[P4344 [SHOI2015] 脑洞治疗仪]

[P4344 [SHOI2015] 脑洞治疗仪]

时间:2024-11-11 18:43:27浏览次数:1  
标签:lmx cnt int P4344 mx ls SHOI2015 治疗仪 rmx

P4344 [SHOI2015] 脑洞治疗仪

说句闲话: 模拟赛因为没注意push_up痛失70pts

Solution:

感觉比较好写的线段树,维护几个变量:
\(lmx,rmx,mx,cnt\) ,lmx表示该区间从左端点开始的最长连续脑洞的长度,rmx,mx类似.cnt表示该区间内有多少个点是0

然后注意一下push_up:

void push_up(Tree &T,Tree L,Tree R,int l,int r)
{
    T.lmx=L.lmx,T.rmx=R.rmx;
    if(L.lmx==L.len)T.lmx+=R.lmx;
    if(R.rmx==R.len)T.rmx+=L.rmx;
    T.mx=max(L.mx,R.mx);
    T.mx=max(T.mx,L.rmx+R.lmx);
    T.cnt=L.cnt+R.cnt;
    T.len=L.len+R.len;
}

由于本人实现比较抽象,所以当push_up需要用来统计答案时,一定要对答案的l,r进行正确的赋值与更新

然后这题就做完了

Code:

#include<bits/stdc++.h>
const int N=2e5+5;
using namespace std;
//Segment_Tree
#define ls x<<1
#define rs x<<1|1
struct Tree{
    int lmx,rmx,mx,tag,cnt,len;
}t[N<<2];
void push_up(Tree &T,Tree L,Tree R,int l,int r)
{
    T.lmx=L.lmx,T.rmx=R.rmx;
    if(L.lmx==L.len)T.lmx+=R.lmx;
    if(R.rmx==R.len)T.rmx+=L.rmx;
    T.mx=max(L.mx,R.mx);
    T.mx=max(T.mx,L.rmx+R.lmx);
    T.cnt=L.cnt+R.cnt;
    T.len=L.len+R.len;
}
void push_down(int x,int l,int r)
{
    if(t[x].tag==-1)return;
    int mid=l+r>>1;int len1=mid-l+1,len2=r-(mid+1)+1;
    int tag=t[x].tag;
    t[ls].cnt=t[ls].lmx=t[ls].mx=t[ls].rmx=len1*tag;
    t[rs].cnt=t[rs].lmx=t[rs].mx=t[rs].rmx=len2*tag;
    t[ls].tag=t[rs].tag=tag;
    //<<"push_down:"<<l<<" "<<r<<" "<<t[x].tag<<"="<<t[ls].cnt<<" "<<t[rs].cnt<<"\n";
    t[x].tag=-1;
}
void build(int x,int l,int r)
{
    t[x].len=r-l+1;
    t[x].cnt=t[x].lmx=t[x].rmx=t[x].mx=0;
    t[x].tag=-1;
    if(l==r)return;
    int mid=l+r>>1;
    build(ls,l,mid);build(rs,mid+1,r);
}
void get(int x,int l,int r,int L,int R,int &res)
{
    if(L<=l&&r<=R)
    {
        res+=r-l+1-t[x].cnt;
        t[x].cnt=t[x].lmx=t[x].mx=t[x].rmx=r-l+1;
        t[x].tag=1;
        //<<"get:"<<l<<" "<<r<<"="<<t[x].lmx<<" "<<t[x].rmx<<"=="<<t[x].mx<<" cnt:"<<t[x].cnt<<" tag:"<<t[x].tag<<"\n";
        return ;
    }
    int mid=l+r>>1;
    push_down(x,l,r);
    if(L<=mid)get(ls,l,mid,L,R,res);
    if(mid<R) get(rs,mid+1,r,L,R,res);
    push_up(t[x],t[ls],t[rs],l,r);
    //<<"get:"<<l<<" "<<r<<"="<<t[x].lmx<<" "<<t[x].rmx<<"=="<<t[x].mx<<" cnt:"<<t[x].cnt<<" tag:"<<t[x].tag<<"\n";

}
void ask(int x,int l,int r,int L,int R,int &res)
{
    if(R<L)return ;
    //<<"ask:"<<l<<" "<<r<<" "<<L<<" "<<R<<"="<<t[x].cnt<<"\n";
    if(L<=l&&r<=R)
    {
        res+=t[x].cnt;
        return;
    }
    int mid=l+r>>1;
    push_down(x,l,r);
    if(L<=mid)ask(ls,l,mid,L,R,res);
    if(mid<R) ask(rs,mid+1,r,L,R,res);
}
int find(int x,int l,int r,int k)
{
    if(l==r)
    {
        return l;
    }
    int mid=l+r>>1;
    push_down(x,l,r);
    if(k>t[ls].cnt) return find(rs,mid+1,r,k-t[ls].cnt);
    else return find(ls,l,mid,k);
}
void fix(int x,int l,int r,int L,int R)
{
    if(L<=l&&r<=R)
    {
        t[x].cnt=t[x].tag=0;
        t[x].lmx=t[x].mx=t[x].rmx=0;
        return ;
    }
    int mid=l+r>>1;
    push_down(x,l,r);
    if(L<=mid)fix(ls,l,mid,L,R);
    if(mid<R) fix(rs,mid+1,r,L,R);
    push_up(t[x],t[ls],t[rs],l,r);
}
void query(int x,int l,int r,int L,int R,Tree &res)
{
    if(L<=l&&r<=R)
    {
        //<<l<<" "<<r<<"="<<t[x].cnt<<"\n";
        push_up(res,res,t[x],l,r);
        return;
    }
    int mid=l+r>>1;
    push_down(x,l,r);
    if(L<=mid)query(ls,l,mid,L,R,res);
    if(mid<R) query(rs,mid+1,r,L,R,res);
}
int n,m;
void work()
{
    cin>>n>>m;
    build(1,1,n);
    for(int i=1,opt,l,r,L,R,k;i<=m;i++)
    {
        k=0;
        scanf("%d%d%d",&opt,&l,&r);
        if(opt==0)
        {
            get(1,1,n,l,r,k);
        }
        if(opt==1)
        {
            scanf("%d%d",&L,&R);
            get(1,1,n,l,r,k);
            int pre=0;
            ask(1,1,n,1,L-1,pre);
            k+=pre;
            if(k==0)continue;
            int pos=min(find(1,1,n,k),R);
            //<<"fix:"<<pre<<" "<<k-pre<<" "<<pos<<"\n";
            fix(1,1,n,L,pos);
        }
        if(opt==2)
        {
            Tree ans=(Tree){0,0,0,0,0,0};
            query(1,1,n,l,r,ans);
            printf("%d\n",ans.mx);
        }
    }
}
int main()
{
    //freopen("instrument.in","r",stdin);
    //freopen("instrument.out","w",stdout);
    work();
    return 0;
}

标签:lmx,cnt,int,P4344,mx,ls,SHOI2015,治疗仪,rmx
From: https://www.cnblogs.com/LG017/p/18540323

相关文章

  • P4344 [SHOI2015] 脑洞治疗仪——线段树
    [SHOI2015]脑洞治疗仪题目描述曾经发明了自动刷题机的发明家SHTSC又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置。为了简单起见,我们将大脑视作一个01序列。\(1\)代表这个位置的脑组织正常工作,\(0\)代表这是一块脑洞。10......
  • P4343 [SHOI2015] 自动刷题机(最详细版本 通俗易懂)
    题目背景曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机——一种可以自动AC题目的神秘装置。题目描述自动刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序。每秒,自动刷题机的代码生成模块会有两种可能的结果:1.写了 x 行代码2......
  • 【SHOI2015】自动刷题机
    一道朴素的二分题,二分的基础很不好所以选择了这道本道题主要进行二分的考察容易发现,对于给定的序列,n越大能过的题是越少的,所以可以二分来求刚好过k道题的左右边界。若mid大于k,即做得太多了,就将l右移。若mid小于k,即做得太少了,就将r左移。代码实现:#include<bits/stdc++.h>u......
  • P4345 [SHOI2015] 超能粒子炮·改 题解
    P4345[SHOI2015]超能粒子炮·改题解求\[\sum_{i=0}^k\binom{n}{i}\pmod{2333}\]思路这种模数小的组合数计数问题可以考虑Lucas定理,试试呗。如果按余数分类不好优化,可以按商分类求和,这样一来套个前缀和可以得到一个递推式,注意最后一块商可能是不整的,单独拿出来即可。......
  • 进行一个脑洞治疗仪的保存
    #include<iostream>#include<fstream>#include<algorithm>//#defineintlonglongusingnamespacestd;structnode_t{ intl,r; intlval,rval,val; intsum,tag;#definel(x)tr[x].l#definer(x)tr[x].r#definelval(x)tr[x].lval#de......
  • 脑洞治疗仪
    P4344[SHOI2015]脑洞治疗仪翻译题目\(0\quadl\quadr\):区间置\(0\)。\(1\quadl_0\quadr_0\quadl_1\quadr_1\):将\([l_0,r_0]\)中的\(1\)取出,填到\([l_1,r_1]\)(从左到右填入,多出去的扔掉)。\(2\quadl\quadr\),查询区间内最大连续\(0\)的长度。思路我们......
  • P4344 SHOI2015 脑洞治疗仪
    \(P4344\)[\(SHOI2015\)]脑洞治疗仪一、题目描述曾经发明了自动刷题机的发明家\(SHTSC\)又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置。为了简单起见,我们将大脑视作一个\(01\)序列。\(1\)代表这个位置的脑组织正常工作,\(0\)代表......
  • P4343 [SHOI2015]自动刷题机
    https://www.luogu.com.cn/problem/P4343 #include<iostream>usingnamespacestd;constintN=1e5+2;#defineintlonglongconstintinf=1e15;inta[N],n......
  • BZOJ 4592 [Shoi2015]脑洞治疗仪
    题目链接:​​传送门​​​Description曾经发明了自动刷题机的发明家SHTSC又公开了他的新发明:脑洞治疗仪–一种可以治疗他因为发明而日益增大的脑洞的神秘装置。为了简单起......