[CF145E]Lucky Queries

145E:Lucky Queries

题意简述

维护一个只有数字 4 7的数列,以下有两种操作:
1.将 [l,r] 区间 4 变为7 7 变为4
2.询问全局最长不下降子序列的长度。
输出所有2操作的答案

思路

线段树维护。
维护四个信息:
1.区间 4 的个数。
2.区间7的个数。
3.区间不降子序列的长度。
4.区间不升子序列的长度。

代码

#include<cstdio>
#include<iostream>
using namespace std;
int n,m,u,v;
char seq[1000010],opt[10];
namespace Segtree
{
    struct Node{
        int f,s,fs,sf,rev;
    }tree[4000010];
    void pushup(int node)
    {
        tree[node].f=tree[node<<1].f+tree[node<<1|1].f;
        tree[node].s=tree[node<<1].s+tree[node<<1|1].s;
        tree[node].fs=max(tree[node<<1].f+tree[node<<1|1].fs,tree[node<<1].fs+tree[node<<1|1].s);
        tree[node].sf=max(tree[node<<1].s+tree[node<<1|1].sf,tree[node<<1].sf+tree[node<<1|1].f);
    }
    void pushdown(int node)
    {
        if (tree[node].rev)
        {
            swap(tree[node<<1].s,tree[node<<1].f);
            swap(tree[node<<1].sf,tree[node<<1].fs);
            tree[node<<1].rev^=1;
            swap(tree[node<<1|1].s,tree[node<<1|1].f);
            swap(tree[node<<1|1].sf,tree[node<<1|1].fs);
            tree[node<<1|1].rev^=1;
            tree[node].rev=0;
        }
    }
    void build(int l,int r,int node)
    {
        if (l==r)
        {
            if (seq[l]=='4')
                tree[node].f=tree[node].sf=tree[node].fs=1;
            else
                tree[node].s=tree[node].sf=tree[node].fs=1;
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,node<<1);
        build(mid+1,r,node<<1|1);
        pushup(node);
    }
    void modify(int L,int R,int l,int r,int node)
    {
        if (L<=l&&r<=R)
        {
            tree[node].rev^=1;
            swap(tree[node].s,tree[node].f);
            swap(tree[node].sf,tree[node].fs);
            return;
        }
        pushdown(node);
        int mid=(l+r)>>1;
        if (L<=mid)
            modify(L,R,l,mid,node<<1);
        if (R>mid)
            modify(L,R,mid+1,r,node<<1|1);
        pushup(node);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    scanf("%s",seq+1);
    Segtree::build(1,n,1);
    for (int i=1;i<=m;i++)
    {
        scanf("%s",opt);
        if (opt[0]=='c')
            printf("%d\n",Segtree::tree[1].fs);
        else
        {
            scanf("%d%d",&u,&v);
            Segtree::modify(u,v,1,n,1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值