题目链接:点击查看

题目大意:给出一个长度为 nnn 的数字序列 aaa 和 010101 序列 bbb,需要执行 mmm 次操作,每次操作分为如下三种类型:

  1. 1 x y:修改 a[x]=ya[x]=ya[x]=y
  2. 2 l r:区间 [l,r][l,r][l,r] 内的 bbb 置反
  3. 3 l r:输出区间 [l,r][l,r][l,r] 的贡献

最后说一下区间 [l,r][l,r][l,r] 的贡献为,首先找到区间 [l,r][l,r][l,r] 内的 “最长不下降子序列”,设其为 {p1,p2,...,pk}\{p_1,p_2,...,p_k\}{p1​,p2​,...,pk​},需要满足:

  1. p1=lp_1=lp1​=l
  2. ap1≤ap2≤ap3...a_{p_1}\le a_{p_2} \le a_{p_3}...ap1​​≤ap2​​≤ap3​​...
  3. 对于任意 j∈(pi,pi+1)j\in(p_i,p_{i+1})j∈(pi​,pi+1​),满足 aj<aia_j<a_iaj​<ai​

然后将数组 bbb 中相应的 010101 序列取出,即 {bp1,bp2,bp3,...,bpk}\{b_{p_1},b_{p_2},b_{p_3},...,b_{p_k}\}{bp1​​,bp2​​,bp3​​,...,bpk​​}

贡献就是 ∑i=1k[bi≠bi−1]\sum\limits_{i=1}^{k}[b_i \neq b_{i-1}]i=1∑k​[bi​​=bi−1​]

题目分析:弱化版:HDU - 6406

其实这个题在思路上和弱化版没有区别,只是加了些许条件,只需要对 calcalcal 函数进行一下魔改就可以了

先回顾一下简单版本,如果只需要求解 “最长不下降子序列” 的个数,那么定义 cal(k,mx)cal(k,mx)cal(k,mx) 为前一项为 mxmxmx ,线段树的节点 kkk 所提供的贡献。如何求解?线段树维护一下区间的最大值,分成两种情况讨论:

  1. 左子树的 mmaxmmaxmmax 小于 mxmxmx:那么左子树没有贡献,只需要递归右子树返回 cal(k<<1∣1,mx)cal(k<<1|1,mx)cal(k<<1∣1,mx) 即可
  2. 左子树的 mmaxmmaxmmax 大于等于 mxmxmx:左右子树都有可能有贡献,答案为 cal(k<<1,mx)+cal(k<<1∣1,mx)cal(k<<1,mx)+cal(k<<1|1,mx)cal(k<<1,mx)+cal(k<<1∣1,mx)

这里为了方便追踪 mxmxmx 的状态,我们将其作为引用或者全局变量进行传值,因为在线段树中检索的顺序是先左后右,宏观来看就是从左向右扫描序列的过程,所以实时更新 mxmxmx 也就模拟了题目中的不断寻找 “最长不下降子序列” 的过程了。

然后就是我们发现上面的第二种情况的复杂度有点不乐观,但是我们不难看出,在递归完左子树后,右子树的答案就完全受左子树所影响了,而对于子树 kkk 来说,我们早就通过 pushuppushuppushup 维护好答案了,所以可以 O(1)O(1)O(1) 计算右子树的贡献为 cnt[k]−cnt[lc[k]]cnt[k]-cnt[lc[k]]cnt[k]−cnt[lc[k]]

所以就简单描述出了弱化版本的 O(nlog2n)O(nlog^2n)O(nlog2n) 的做法

回到本题我们该如何维护该序列映射到数组 bbb 上的贡献呢,其实只需要在 calcalcal 函数中额外维护一个参数就可以了:cal(k,mx,pre)cal(k,mx,pre)cal(k,mx,pre) 代表的是,前一项为 mxmxmx,mxmxmx 所代表的位置的 bbb 的状态为 preprepre,子树 kkk 所提供的贡献。在 calcalcal 递归到叶子节点时直接计算答案就好了

需要注意的是,在上述两种情况中的第二种情况,虽然优化了访问右子树的过程,但是返回的时候别忘了更新 mxmxmx 和 preprepre 为右子树结束时的状态(因为要从左到右扫描原序列)

剩下的两种操作无非就是单点修改和区间修改,中规中矩的线段树操作就不多说了

计算答案时的初始值根据题意设置成 a[l]a[l]a[l] 和 b[l]b[l]b[l] 就可以了

代码:

// Problem: xay loves monotonicity
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/11258/B
// Memory Limit: 524288 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) (x&-x)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f;
}
template<typename T>
inline void write(T x)
{if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
struct Node {int l,r;int mmax,flag,lazy,cnt;
}tree[N<<2];
int a[N],b[N];
void pushdown(int k) {if(tree[k].lazy) {tree[k].lazy=0;tree[k<<1].flag^=1,tree[k<<1|1].flag^=1;tree[k<<1].lazy^=1,tree[k<<1|1].lazy^=1;}
}
int cal(int k,int &mx,int &pre) {//在子树k中以mx为起点的贡献,pre为mx位置的b的值if(tree[k].mmax<mx) return 0;if(tree[k].l==tree[k].r) {if(mx<=tree[k].mmax) {int ans=tree[k].flag!=pre;mx=tree[k].mmax,pre=tree[k].flag;return ans;} else return 0;}pushdown(k);if(mx>tree[k<<1].mmax) return cal(k<<1|1,mx,pre);else {int ans=cal(k<<1,mx,pre)+tree[k].cnt-tree[k<<1].cnt;mx=tree[k].mmax,pre=tree[k].flag;return ans;}
}
void pushup(int k) {if(tree[k<<1].mmax>tree[k<<1|1].mmax) {tree[k].mmax=tree[k<<1].mmax,tree[k].flag=tree[k<<1].flag;} else {tree[k].mmax=tree[k<<1|1].mmax,tree[k].flag=tree[k<<1|1].flag;}int mx=tree[k<<1].mmax,pre=tree[k<<1].flag;tree[k].cnt=tree[k<<1].cnt+cal(k<<1|1,mx,pre);
}
void build(int k,int l,int r) {tree[k]={l,r,0,0,0,0};if(l==r) {tree[k].mmax=a[l],tree[k].flag=b[l];return;}int mid=(l+r)>>1;build(k<<1,l,mid),build(k<<1|1,mid+1,r);pushup(k);
}
void update_a(int k,int pos,int val) {if(tree[k].l==tree[k].r) {tree[k].mmax=val;return;}pushdown(k);int mid=(tree[k].l+tree[k].r)>>1;if(pos<=mid) update_a(k<<1,pos,val);else update_a(k<<1|1,pos,val);pushup(k);
}
void update_b(int k,int l,int r) {if(tree[k].l>r||tree[k].r<l) return;if(tree[k].l>=l&&tree[k].r<=r) {tree[k].flag^=1,tree[k].lazy^=1;return;}pushdown(k);update_b(k<<1,l,r),update_b(k<<1|1,l,r);pushup(k);
}
int query_ans(int k,int l,int r,int &mx,int &pre) {if(tree[k].l>r||tree[k].r<l) return 0;if(tree[k].l>=l&&tree[k].r<=r) {if(mx<=tree[k].mmax) return cal(k,mx,pre);else return 0;}pushdown(k);return query_ans(k<<1,l,r,mx,pre)+query_ans(k<<1|1,l,r,mx,pre);
}
int query_a(int k,int pos) {if(tree[k].l==tree[k].r) return tree[k].mmax;pushdown(k);int mid=(tree[k].l+tree[k].r)>>1;if(pos<=mid) return query_a(k<<1,pos);else return query_a(k<<1|1,pos);
}
int query_b(int k,int pos) {if(tree[k].l==tree[k].r) return tree[k].flag;pushdown(k);int mid=(tree[k].l+tree[k].r)>>1;if(pos<=mid) return query_b(k<<1,pos);else return query_b(k<<1|1,pos);
}
int main()
{#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n,m;read(n);for(int i=1;i<=n;i++) read(a[i]);for(int i=1;i<=n;i++) read(b[i]);build(1,1,n);read(m);while(m--) {int op,x,y;read(op),read(x),read(y);if(op==1) update_a(1,x,y);else if(op==2) update_b(1,x,y);else if(op==3) {int mx=query_a(1,x),pre=query_b(1,x);cout<<query_ans(1,x,y,mx,pre)<<endl;}}return 0;
}

2021牛客多校7 - xay loves monotonicity(线段树区间合并)相关推荐

  1. 2021牛客暑期多校训练营7 xay loves monotonicity 线段树区间合并

    传送门 文章目录 题意: 思路: 题意: 题面挺绕口的,还是看原题比较好. 大概的意思就是让你从给定的区间中选择一个以左端点为起点的一个上升子序列,让后将这些下标存下来,在bbb中将这些位置拿出来后, ...

  2. 2021牛客多校7 - xay loves trees(dfs序+主席树-标记永久化)

    题目链接:点击查看 题目大意:给出两棵以点 111 为根节点的有根树,现在要求满足条件的最大集合: 在第一棵树中,集合内的任意两个点都必须满足祖先关系,即 uuu 是 vvv 的祖先或 vvv 是 u ...

  3. 2021牛客第四场-E Tree Xor-线段树区间异或

    https://ac.nowcoder.com/acm/contest/11255/E 题目大意:有n个点,每一点有一个区间[l,r]范围的权值可能,有n-1条边,边上的权值为w,w=w(u)^w(v ...

  4. LCS(2021牛客多校4)

    LCS(2021牛客多校4) 题意: 让你构造三个字符串s1,s2,s3,长度均为n,要求LCS(s1,s2)=a,LCS(s2,s3)=b,LCS(s1,s3)=c 题解: 先考虑三个串互相LCS为 ...

  5. 【2021牛客多校2】F-Girlfriend 计算几何

    2021牛客多校2-F F-Girlfriend 题目大意 给出四个点 A , B , C , D A, B, C, D A,B,C,D 另有两点 P 1 , P 2 P_1, P_2 P1​,P2​ ...

  6. Codeforces 444C DZY Loves Colors 线段树区间更新

    // Codeforces 444C DZY Loves Colors 线段树区间更新// 题目链接:// http://codeforces.com/problemset/problem/444/C ...

  7. K-Stack 2021牛客多校2

    链接:https://ac.nowcoder.com/acm/contest/11253/K 来源:牛客网 题目描述 ZYT had a magic permutation a1,a2,⋯ ,an a ...

  8. 2021牛客多校第八场补题 D-OR

    链接:https://ac.nowcoder.com/acm/contest/11259/D 来源:牛客网 题目描述 There are two sequences of length n−1n-1n ...

  9. 2021牛客多校第五场补题

    B-Boxes 链接:https://ac.nowcoder.com/acm/contest/11256/B 来源:牛客网 题目描述 There're nn_{}n​ boxes in front o ...

最新文章

  1. oracle rac安装
  2. Dataset之AllstateClaimsSeverity:AllstateClaimsSeverity数据集(Kaggle2016竞赛)的简介、下载、案例应用之详细攻略
  3. Ubuntu 16.04 下安装VMware Tools(三行命令搞定,亲测好使)
  4. CodeForces - 1326D2 Prefix-Suffix Palindrome (Hard version)(马拉车/回文自动机)
  5. 浅谈五大Python Web框架
  6. [EDA] 2.2 简单PLD结构原理-潘松版
  7. 单机安装oracle,单机安装oracle系统
  8. python numpy库安装 mac_MAC系统下安装Python模块
  9. mysql中regexp_substr_oracle REGEXP_SUBSTR函数
  10. ssk 2g安国6981量产xp
  11. 细数百度小程序踩的坑
  12. arcgispython空间插值_python2 使用arcpy自定义GIS工具箱,实现excel读取、空间插值
  13. android 7.1 默认壁纸拉伸问题
  14. 什么是LSI关键词?LSI关键词怎么用?2019
  15. win10计算机切换用户,win10系统账户切换的三种方法
  16. android8.1如何升级,关于android8.1实现多个app升级时的注意事项
  17. QQ.COM二级域名大全 腾讯旗下产品大全
  18. 软题库 - 软考题库,云题库,智能测试
  19. Win 10-jdk 8 下载和安装步骤
  20. 游戏画质修改器GFX工具箱(GFX tool)_9.9.8特别版

热门文章

  1. pexpect oracle,expect免交互脚本编程
  2. MySQL where后面的行子查询使用
  3. 锁的释放流程-ReentrantLock.tryRelease
  4. Spring框架版本命名规则
  5. 扩展--使用队列来优化递归操作完成文件下载
  6. flume案例-flume级联-组件分析
  7. MapReduce-计数器
  8. 守护线程与非守护线程
  9. 缺省参数-缺省参数的注意事项
  10. 树和二叉树的基本概念(二级)