zoukankan      html  css  js  c++  java
  • 题解 CF145E Lucky Queries

    线段树。

    在树中我们维护四个东西:最长不下降子序列的长度,最长不上升子序列的长度,(4)的个数和(7)的个数。

    线段树最重要的是(push\,up),也就是合并。

    显然(4)的个数和(7)的个数就直接加一下,没什么好说的。

    因为数列中不是(4)就是(7),所以这个最长不下降子序列一定有一个(4)(7)的分界点。

    如果这个分界点在左儿子里,那么父节点的最长不下降子序列的长度就是左儿子的最长不下降子序列长度加上右儿子的(7)的个数。

    如果这个分界点在右儿子里,那么父节点的最长不下降子序列的长度就是左儿子的(4)的个数加上右儿子的最长不下降子序列长度。

    最长不上升子序列的长度同理。

    这部分的代码

    struct node
    {
    	ll l,r,mid,vals,valx,num4,num7;//vals是最长不上升子序列长度,valx是最长不下降子序列长度
    	bool tag;//lazy标记
    }seg[N<<2];
    inline void pushup(re ll pos)
    {
    	seg[pos].vals=max(seg[pos<<1].vals+seg[pos<<1|1].num7,seg[pos<<1].num4+seg[pos<<1|1].vals);
    	seg[pos].valx=max(seg[pos<<1].valx+seg[pos<<1|1].num4,seg[pos<<1].num7+seg[pos<<1|1].valx);
    	seg[pos].num4=seg[pos<<1].num4+seg[pos<<1|1].num4;
    	seg[pos].num7=seg[pos<<1].num7+seg[pos<<1|1].num7;
    	return;
    }
    

    建树就没什么可说的了,和正常的线段树建树一样,最长不上升子序列长度和最长不下降子序列的长度都赋为(1)

    inline void build(re ll pos,re ll l,re ll r)
    {
    	seg[pos].l=l;
    	seg[pos].r=r;
    	seg[pos].mid=l+r>>1;
    	if(l==r)
    	{
    		seg[pos].vals=seg[pos].valx=1;
    		seg[pos].num4=(a[l]==4);
    		seg[pos].num7=(a[l]==7);
    	}
    	else
    	{
    		build(pos<<1,l,seg[pos].mid);
    		build(pos<<1|1,seg[pos].mid+1,r);
    		pushup(pos);	
    	}
    	return;
    }
    

    修改操作就直接把最长不上升子序列的长度和最长不下降子序列的长度交换,(4)的数量和(7)的数量交换。

    标记下传

    inline void add(re ll pos)
    {
    	seg[pos].tag^=1;
    	swap(seg[pos].num4,seg[pos].num7);
    	swap(seg[pos].valx,seg[pos].vals);
    	return;
    }
    inline void pushdown(re ll pos)
    {
    	if(!seg[pos].tag)
    		return;
    	add(pos<<1);
    	add(pos<<1|1);
    	seg[pos].tag^=1;
    	return;
    }
    

    区间修改

    inline void upgrade(re ll pos,re ll l,re ll r)
    {
    	if(seg[pos].l>=l&&seg[pos].r<=r)
    		return add(pos);
    	else if(seg[pos].l>r||seg[pos].r<l)
    		return;
    	pushdown(pos);
    	upgrade(pos<<1,l,r);
    	upgrade(pos<<1|1,l,r);
    	pushup(pos);
    	return;
    }
    

    每次询问的结果就是seg[1].vals

    注意这个毒瘤的没有空格的输入就好了。

  • 相关阅读:
    python操作elasticsearch
    php源码的编译
    linux 访问windows 共享文件
    list容器排除重复单词的程序
    求组合数m_n
    简单堆排序
    快速排序
    判断点在直线左侧或者右侧
    求取点到直线的距离
    求给定三个点的夹角
  • 原文地址:https://www.cnblogs.com/CelticBlog/p/13531726.html
Copyright © 2011-2022 走看看