题目链接:点击查看

题目分析:刚看到这个题目的时候,口胡了一个假算法,觉得对于每次询问的操作 [l,r][l,r][l,r] ,只需要找到指令集区间 [l,r][l,r][l,r] 内覆盖到点 kkk 的最大并集,然后求出这段区间中 aaa 数组的最大值就是答案了,这样一来直接用线段树维护一下数组 aaa,再用主席树维护一下区间交集即可

但后来转念一想,覆盖的区间还有时序问题,也就是两个区间执行的先后顺序不同,会造成不一样的结果,到此为止这个题也就卡住了

今天看了题解和杨大佬讨论了一下就豁然开朗了,其实卡住的部分就差预处理出一个树上倍增了

因为本题中的指令集操作,本质上是将一个区间的数值都赋值为该区间的最大值。所以我们的最终目标仍然是需要找到包含点 kkk 的区间向左向右分别可以扩展到什么位置,记为 [ll,rr][ll,rr][ll,rr],那么答案就是数组 aaa 在 [ll,rr][ll,rr][ll,rr] 中的最大值了,下面以向右扩展为例来讲解,向左扩展的话只需要类比过去就好啦

将指令集视为一棵树,对于第 iii 个指令来说,其代表的区间为 [li,ri][l_i,r_i][li​,ri​],因为我们需要尽可能向右扩展,所以我们查找一下点 rir_iri​ 最后一次被哪个指令集所覆盖,记为 jjj,那么此时就会产生一条 j−>ij->ij−>i 的有向边,如此建图的话,最后就会形成一棵以点 000 为根节点的树(其实严格意义上来说,是以点 000 为根节点的一棵森林)

而且不难发现,假设 jjj 到 iii 有一条边,且 jjj 是 iii 的父节点,那么满足两个性质:

  1. j<ij<ij<i
  2. rj>=rir_j>=r_irj​>=ri​

所以对于给定的点 kkk ,我们只需要找到其最多可以扩展到的位置就是上文中需要求的 rrrrrr 了

而不断向上跳 fafafa 的过程也可以利用倍增快速实现

如果每次询问的都是 [1,m][1,m][1,m] 中的指令集,那么问题就已经解决了所以现在只剩下了一个问题,那就是指令集限制在 [l,r][l,r][l,r] 内该如何实现呢?

注意到上面提到的,建出来的树的性质一,即从根节点到任意节点的编号都是单调递增的,所以我们可以从第 rrr 个指令集不断向上跳,跳到深度最低,且指令集的编号仍然大于等于 lll 的那个祖先为止

所以现在的目标就转换为了,如何建出上文中的那棵树呢?其实只需要实现下面两个操作即可:

  1. 将某个版本的的某个区间覆盖成指定颜色
  2. 查询某个版本指定位置的颜色的最大值

因为涉及到了历史版本和区间问题,所以用主席树来维护就好啦

需要注意的是,区间修改要用到标记永久化,并且对于某段区间的修改,保守估计会有 3logn3logn3logn 个节点会被修改,所以主席树的数组大小需要注意一下

代码:

// #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=1e5+100;
int n,L[N][25],R[N][25],ql[N],qr[N];
struct Seg {struct Node {int l,r,mmax;}tree[N<<2];void pushup(int k) {tree[k].mmax=max(tree[k<<1].mmax,tree[k<<1|1].mmax);}void build(int k,int l,int r) {tree[k]={l,r,0};if(l==r) {read(tree[k].mmax);return;}int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k);}void update(int k,int pos,int val) {if(tree[k].l==tree[k].r) {tree[k].mmax=val;return;}int mid=(tree[k].l+tree[k].r)>>1;if(pos<=mid) {update(k<<1,pos,val);} else {update(k<<1|1,pos,val);}pushup(k);}int query(int k,int l,int r) {if(tree[k].l>r||tree[k].r<l) {return 0;}if(tree[k].l>=l&&tree[k].r<=r) {return tree[k].mmax;}return max(query(k<<1,l,r),query(k<<1|1,l,r));}
}SEG;
struct CMT {struct Node {int l,r,lazy;}tree[N*60];int root[N],tot;int newnode() {tot++;tree[tot].l=tree[tot].r=tree[tot].lazy=0;return tot;}void update(int &k,int l,int r,int L,int R,int val) {//[l,r]:target [L,R]:curif(L>r||R<l) {return;}int nk=newnode();tree[nk]=tree[k];k=nk;if(L>=l&&R<=r) {tree[k].lazy=val;return;}int mid=(L+R)>>1;update(tree[k].l,l,r,L,mid,val);update(tree[k].r,l,r,mid+1,R,val);}int query(int k,int L,int R,int pos,int val) {//[L,R]:curval=max(val,tree[k].lazy);if(L==R) {return val;}int mid=(L+R)>>1;if(pos<=mid) {return query(tree[k].l,L,mid,pos,val);} else {return query(tree[k].r,mid+1,R,pos,val);}}void update(int l,int r,int val) {//将[l,r]染色成valupdate(root[val],l,r,1,n,val);}int query(int k,int pos) {//查询第k个版本点pos的颜色return query(root[k],1,n,pos,0);}
}CMT;
int main()
{#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int m,q;read(n),read(m),read(q);SEG.build(1,1,n);for(int i=1;i<=m;i++) {read(ql[i]),read(qr[i]);L[i][0]=CMT.query(i-1,ql[i]);R[i][0]=CMT.query(i-1,qr[i]);CMT.root[i]=CMT.root[i-1];CMT.update(ql[i],qr[i],i);for(int j=1;j<=20;j++) {L[i][j]=L[L[i][j-1]][j-1];R[i][j]=R[R[i][j-1]][j-1];}}while(q--) {int op;read(op);if(op==1) {int x,y;read(x),read(y);SEG.update(1,x,y);} else if(op==2) {int l,r,k;read(l),read(r),read(k);int ll=CMT.query(r,k);int rr=ll;for(int i=20;i>=0;i--) {if(R[rr][i]>=l) {rr=R[rr][i];}if(L[ll][i]>=l) {ll=L[ll][i];}}if(ll<l) {printf("%d\n",SEG.query(1,k,k));} else {printf("%d\n",SEG.query(1,ql[ll],qr[rr]));}}}return 0;
}

2020-2021年度第二届全国大学生算法设计与编程挑战赛 (春季赛)- 天才的操作(线段树+主席树+树上倍增)相关推荐

  1. 2020-2021年度第二届全国大学生算法设计与编程挑战赛(冬季赛)题解

    热身赛 排列巨人 题目描述: 海的那边是敌人! 为了夺回自由,艾尔迪亚帝国开始筹备起帝国巨人军队,利用艾伦始祖巨人之力,来指挥军队征战. 现在有12名巨人,他们的个子非常奇怪,第ii名巨人的身高为ii ...

  2. 2020-2021年度第二届全国大学生算法设计与编程挑战赛(春季赛)【部分题题解】

    2021年6月份打的比赛,现在才开始复盘. 目录 A: 智慧果[难度: 签到题 / 知识点: 递推] B: Xanadu[难度: 中 / 知识点: 最短路] C: 这是一道大难题[难度: 一般 / 知 ...

  3. 2020-2021年度第二届全国大学生算法设计与编程挑战赛题解(冬季赛)

    塔 你在最后那场博弈中败下阵来,却意外穿越到了海拉尔大陆!是你吗林克? 初来到海拉尔大陆的你,有些许的局促,但当你看到塔,或许一切的一切都迎刃而解. 一个层高为n的字母塔的定义为: 共n行,由字母组成 ...

  4. 2020-2021年度第二届全国大学生算法设计与编程挑战赛 (秋季赛)-正式赛-详细题解

    文章目录 A小x的奇遇-adventure B数位dp-dp F大数据分析-data A小x的奇遇-adventure #include <cstdio>const int N = 1e6 ...

  5. 第二届全国大学生算法设计与编程挑战赛(冬季赛)题解

    文章目录 塔 日记 神仙爱采药 奇怪的小鸭子也增加了 关于哥俩好的数字这件事 出题人说这道题是一个签到题 但更爱字符串 今天下午上课差点把这个比赛忘了,对了6个,应该算一般吧,应该是个铜奖(前百分之3 ...

  6. 第二届全国大学生算法设计与编程挑战赛(赛题,共10个)

    第二届全国大学生算法设计与编程挑战赛 比赛日期:2020.11.15 早上9:00--下午14:00 共十个赛题. loading...... x = 13930 y = 457439count = ...

  7. 2022-2023年度第四届全国大学生算法设计与编程挑战赛(秋季赛)【热身赛】h-4题 花灯

    一.问题描述 二.分析: 此题的问题描述部分的第一句话:"花灯有n个,排列成l行供大家欣赏."中,"排列成l行"应与本题求解无关.由题意可知:n个花灯被均分为块 ...

  8. 2021-2022年度第三届全国大学生算法设计与编程挑战赛(夏季赛)

    2021-2022年度第三届全国大学生算法设计与编程挑战赛(夏季赛) 主要是用于记录涉及的知识点,本次比赛是团队赛. http://oj.saikr.com/contest/20/problems 部 ...

  9. 【算法】第三届全国大学生算法设计与编程挑战赛(冬季赛)

    7题金,6题银,5题铜 [参考:2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)题解_int 我的博客-CSDN博客] [参考:2021-2022年度第三届全国大学生算法设计与编程 ...

最新文章

  1. TaintDroid介绍
  2. 单片机 原子性操作_一款深藏功与名的国产单片机——F1C100A
  3. apple给我的感受
  4. 希赛软件设计师视频教程-3.1 进程(第三部分) 标清
  5. 数据报套接字服务端和客户端
  6. TreeSet类的排序
  7. 「机械」4大传动方式优劣对比:机械、电气、气压、液压
  8. Linux|Qt工作笔记-linux系统下安装qt4.5.3版本的详细步骤
  9. 项目遇到技术难题,领导让我假招聘套取解决方案,我没有照做,结果15天后蒙了
  10. Java方法实现是什么意思_Java中实现可调用的最佳方法是什么,需要一段时间才能完成...
  11. 产品特点概述-驰骋工作流
  12. 设定asp服务器外部组件对象的方法是,ASP 3.0对ASP 2.0的改进
  13. 万圣节html代码大全,《方舟:生存进化》万圣节代码大全
  14. Ant design分析后台首页
  15. css margin 塌陷 经典bug
  16. wincc7.4安装授权 全(文件分享)
  17. golang 通过docker 搭建 ocr识别
  18. 自媒体应该怎么入门,这几点教会你
  19. 五款数字孪生软件大比拼:优缺点分析测评报告
  20. Android(安卓),如何查看App渠道号?

热门文章

  1. Nacos源码Notifier异步更新
  2. 数据库唯一主键如何实现幂等性?
  3. 【思考?】什么时候会触发这个策略呢?
  4. ConcurrentHashMap的源码分析-数据迁移阶段的实现分析
  5. acquireQueued
  6. SimpleExecutor.doQuery()-执行的StatementHandler 的query()方法
  7. 一台机器理论能支持的连接数
  8. SpringAOP概念
  9. 文件上传案例阻塞问题
  10. 数据库-事务并发操作问题及并发的控制