P4198 楼房重建
线段树维护以某点为开头的最长不下降子序列

使用下面calc函数能够计算线段树u维护的区间中,以x为开头最长不下降子序列的个数。

calc需要维护区间最值。

template<typename T>
int calc(int u,T x)
{if(tree[u].l==tree[u].r) return tree[u].v>x?1:0;if(tree[u<<1].v<=x) return calc(u<<1|1,x);return tree[u].cnt-tree[u<<1].cnt+calc(u<<1,x);
}

B-xay loves monotonicity

如果本题没有b数组,就是上面的楼房重建,用上面calc函数递归解决问题。

由于存在b数组的操作,首先是区间翻转可以懒标记解决。
对于贡献来说我们同样记录每个区间的最值,并且记录一下最值出现位置pos\text {pos}pos的bposb_{\text{pos}}bpos​值,然后calc过程中记录一个pre即可实现递归。

注意引用的巧妙使用!!!

由于引用不难知道:
int calc(int u,int &mx,int &pre)中的mx\text{mx}mx和pre\text{pre}pre始终表示当前考虑的子序列最后一个值和最后一个值的b

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
template <class T=int> T rd()
{T res=0;T fg=1;char ch=getchar();while(!isdigit(ch)) {if(ch=='-') fg=-1;ch=getchar();}while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res*fg;
}
const int N=200010;
int a[N],b[N],n,m;
struct node
{int l,r;int v,cnt;// 区间最值v 以左端点为起点的最长不下降子序列int bt,tag;// 区间最值位置的b值 懒标记
}tree[N<<2];
void pushdown(int u)
{if(!tree[u].tag) return;tree[u<<1].tag^=1;tree[u<<1|1].tag^=1;tree[u<<1].bt ^=1;tree[u<<1|1].bt ^=1;tree[u].tag=0;
}
int calc(int u,int &mx,int &pre)//在子树u中以mx为起点的贡献,pre为mx位置的b的值
{if(tree[u].v<mx) return 0;if(tree[u].l==tree[u].r){if(tree[u].v>=mx) // 满足不下降{int ans=(tree[u].bt!=pre); // 贡献需要和前一个b不一样mx=tree[u].v,pre=tree[u].bt;// 修改mx和prereturn ans;}return 0;}pushdown(u);if(tree[u<<1].v<mx) return calc(u<<1|1,mx,pre);int ans=calc(u<<1,mx,pre)+tree[u].cnt-tree[u<<1].cnt;mx=tree[u].v,pre=tree[u].bt;return ans;}
void pushup(int u)
{if(tree[u<<1].v>tree[u<<1|1].v)// 区间最值和最值出现位置的b(靠右边)tree[u].v=tree[u<<1].v,tree[u].bt=tree[u<<1].bt;elsetree[u].v=tree[u<<1|1].v,tree[u].bt=tree[u<<1|1].bt;int mx=tree[u<<1].v,pre=tree[u<<1].bt;tree[u].cnt=tree[u<<1].cnt+calc(u<<1|1,mx,pre);
}
void build(int u,int l,int r)
{tree[u]={l,r};if(l==r){tree[u].v=a[l];tree[u].bt=b[l];tree[u].cnt=1;return;}int mid=l+r>>1;build(u<<1,l,mid),build(u<<1|1,mid+1,r);pushup(u);
}
void change(int u,int pos,int v)
{if(tree[u].l==tree[u].r) return tree[u].v=v,void();pushdown(u);int mid=tree[u].l+tree[u].r>>1;if(pos<=mid) change(u<<1,pos,v);elsechange(u<<1|1,pos,v);pushup(u);
}
void filp(int u,int l,int r)
{if(l<=tree[u].l&&tree[u].r<=r){tree[u].bt^=1;tree[u].tag^=1;return;}pushdown(u);int mid=tree[u].l+tree[u].r>>1;if(l<=mid) filp(u<<1,l,r);if(r>mid)filp(u<<1|1,l,r);pushup(u);
}
int query(int u,int l,int r,int &mx,int &pre)
{if(l<=tree[u].l&&tree[u].r<=r) return calc(u,mx,pre);pushdown(u);int mid=tree[u].l+tree[u].r>>1;int v=0;if(l<=mid) v+=query(u<<1,l,r,mx,pre);if(r>mid)v+=query(u<<1|1,l,r,mx,pre);return v;
}
int main()
{n=rd();for(int i=1;i<=n;i++) a[i]=rd();for(int i=1;i<=n;i++) b[i]=rd();build(1,1,n);m=rd();while(m--){int op=rd(),t1=rd(),t2=rd();if(op==1) change(1,t1,t2);else if(op==2) filp(1,t1,t2);else{int mx=-1,pre=-1;// 先假计算上序列一个值的贡献printf("%d\n",query(1,t1,t2,mx,pre)-1);// -1表示删去计算上序列一个值的贡献}}return 0;
}

2021牛客暑期多校训练营7 B-xay loves monotonicity(线段树+不降子序列)相关推荐

  1. 【2021牛客暑期多校训练营7】xay loves trees(dfs序,维护根出发的链)

    F xay loves trees 题意: 给出两棵树,由这两棵树根据规则可以生成一个图,规则如下:如果u , v在第一棵树中满足其中一个点是另一个点祖先且最终所有所选的点都互相联通,在第二棵树中满足 ...

  2. 【2021牛客暑期多校训练营7 】 xay loves count

    题目:点这里 要求:给出一组数,求满足 的i,j,k有多少个 分析:列举ak,对每一个找出满足题意的i,j然后计算有多少个(三个数可以相同,找i,j的范围是0~sqrt(ak): 下面还是队友代码时间 ...

  3. 2021牛客暑期多校训练营9

    2021牛客暑期多校训练营9 题号 题目 知识点 A A Math Challenge B Best Subgraph C Cells D Divide-and-conquer on Tree E E ...

  4. 2021牛客暑期多校训练营5

    2021牛客暑期多校训练营5 题号 题目 知识点 A Away from College B Boxes 概率 C Cheating and Stealing D Double Strings 线性d ...

  5. 2021牛客暑期多校训练营4

    2021牛客暑期多校训练营4 题号 题目 知识点 A Course B Sample Game C LCS D Rebuild Tree E Tree Xor 思维+线段树 F Just a joke ...

  6. 2021牛客暑期多校训练营3

    2021牛客暑期多校训练营3 题号 题目 知识点 A Guess and lies B Black and white C Minimum grid 二分图匹配 D Count E Math 数论+打 ...

  7. 2021牛客暑期多校训练营2

    2021牛客暑期多校训练营2 题号 题目 知识点 A Arithmetic Progression B Cannon C Draw Grids D Er Ba Game E Gas Station F ...

  8. 2021牛客暑期多校训练营1

    2021牛客暑期多校训练营1 题号 题目 知识点 难度 A Alice and Bob 博弈论 B Ball Dropping 计算几何 签到 C Cut the Tree D Determine t ...

  9. 2021牛客暑期多校训练营2,签到题CDFKI

    2021牛客暑期多校训练营2 题号 标题 已通过代码 通过率 团队的状态 A Arithmetic Progression 点击查看 6/72 未通过 B Cannon 点击查看 34/104 未通过 ...

  10. 2021牛客暑期多校训练营1, 签到题DFBG

    2021牛客暑期多校训练营1 题号 标题 已通过代码 通过率 团队的状态 A Alice and Bob 点击查看 1365/5586 通过(博弈论-打表) B Ball Dropping 点击查看 ...

最新文章

  1. php phar 无法创建,php composer.phar install 安装问题
  2. 必须去收藏14个响应式布局的前端开发框架
  3. coso全称是什么_国际贸易术语的全称是什么?
  4. 一次二次开发中的经验与教训(二)
  5. 南邮CTF-MISC-Remove Boyfriend
  6. php程序员跟java一样吗,【后端开辟】php程序员能够转java吗?
  7. 天下第一 txdy (LCT+双指针+线段树)
  8. 宝塔面板服务器ip地址修改_「网站」快速搭建服务器环境及网站
  9. codeforces 679B
  10. 管道泄漏监测系统分布式光纤测温技术方案
  11. C++设计模式从入门到精通——实例说明
  12. 【bat】做个一键连接网络打印机的bat
  13. 时序分析 29 - 时序预测 - 格兰杰因果关系(下) python实践2
  14. 移动端html5广告的优势,移动端H5广告的互动类型探析
  15. 什么样的代码是好代码_什么使好代码3 7
  16. python 文本框不能放表情_用Python自动生成表情包,生活不易多才多艺!
  17. JS初中段考:袖珍西历
  18. linux图片什么格式文件怎么打开,解决Linux平台下无法打开jpg文件(提示: “Not a JPEG file: starts with 0x89 0x50”)的方法...
  19. 《科技创业启示录》一第2章 克里斯·巴顿、菲利普·安格布瑞希、迪拉伊·慕克吉、艾弗里·王 科技创业启示录...
  20. Unity中使用软连接快速切换平台

热门文章

  1. php显示前60个字,DEDECMS中怎么让文章标题栏突破60个字符
  2. 程序显示文本框_【教程】TestComplete测试桌面应用程序教程(二)
  3. java实现网页保存_详解Java两种方式简单实现:爬取网页并且保存
  4. [Qt入门]QTableWidget控件创建
  5. LeetCode 19删除链表的倒数第N个节点-中等
  6. LeetCode 138 复制带随机指针的链表-中等
  7. 数据结构与算法--翻转单词顺序
  8. mysql技术分享--表分区实现
  9. 聊一聊顺序消息(RocketMQ顺序消息的实现机制)
  10. 牛客练习赛69 解方程