点此看题面

大致题意: 有单点修改数字和区间着色两种修改操作,询问你某段区间内包含所有颜色且数字和最小的子区间的数字和,或某段区间内没有重复颜色且数字和最大的子区间的数字和。数据随机。

\(ODT\)维护颜色

看到区间着色且题目中强调数据随机,容易想到使用\(ODT\)去求解。

于是,我们就可以考虑用\(ODT\)来对颜色进行维护。

线段树维护数字和

但是考虑到要求区间数字和,\(ODT\)就很难搞了。

考虑到我们其实可以对于每个询问,每次找到一个合法区间再询问数字和更新答案。

也就是说,可以把维护颜色和维护数字和分开。

那维护数字和自然可以用线段树喽。

其实本来用树状数组似乎更优,但这题由于写法问题可能还会需要求区间\(Min\)或\(Max\),树状数组搞起来就很吃力了。

处理询问

以上大致介绍了,可以用线段树维护数字和,\(ODT\)维护颜色。

接下来,再具体介绍一下如何去处理询问。

考虑到这两种询问实际上都具有单调性,因此可以直接用双指针搞。

我们枚举右端点,然后移动左端点。

  • 对于第一种询问,我们需要在保证颜色数量等于\(c\)的情况下才能移动左端点,然后在移动的同时更新答案(不然统计答案的过程会略显麻烦)。

    而\(c=1\)的情况可能要特判,直接输出这段区间的最小值。

  • 对于第二种询问,我们只需在出现不合法情况,即出现重复颜色时移动左端点。考虑我们此时刚把右端点的颜色加入,若出现重复颜色,必然是由右端点导致的,因此不断移动左端点直至右端点所属颜色出现次数为\(1\)即可。

    但注意,在处理第二种询问时,一旦出现右端点\(Size>1\)的情况,我们在统计完其答案后,需将左端点移动到右端点的位置上,不然就会出现重复颜色。

    同理,在统计第二种询问的答案时,要求左端点的右边界右端点的左边界之间的区间和,不然同样会出现重复颜色。

    而且,在第二种情况时容易漏考虑单个颜色的贡献,因此要初始化\(res\)为整段区间的\(Max\)。

大致就是这些吧。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define INF 1e9
#define Gmax(x,y) (x<(y)&&(x=(y)))
#define Gmin(x,y) (x>(y)&&(x=(y)))
using namespace std;
int n,c,a[N+5];
class FastIO
{private:#define FS 100000#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))#define tn (x<<3)+(x<<1)#define D isdigit(c=tc())int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];public:I FastIO() {A=B=FI;}Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);} Tp I void write(Ty x) {x<0&&(pc('-'),x=-x);W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}Tp I void writeln(Con Ty& x) {write(x),pc('\n');}I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
class SegmentTree//线段树
{private:#define STO l,hl,rt<<1#define ORZ hl+1,r,rt<<1|1#define PU(x) (O[x]=O[x<<1]+O[x<<1|1])int n,v[N+5];struct Interval//维护区间信息{int S,Mx,Mn;I Interval(CI s=0,CI mx=-INF,CI mn=INF):S(s),Mx(mx),Mn(mn){}I Interval operator + (Con Interval& t) Con {return Interval(S+t.S,max(Mx,t.Mx),min(Mn,t.Mn));}}O[N<<2];I void Build(CI l,CI r,CI rt)//建树{if(!(l^r)) return (void)(O[rt]=Interval(v[l],v[l],v[l]));RI hl=l+r>>1;Build(STO),Build(ORZ),PU(rt);}I int qsu(CI l,CI r,CI rt,CI ql,CI qr)//询问区间和{if(ql<=l&&r<=qr) return O[rt].S;RI hl=l+r>>1;return (ql<=hl?qsu(STO,ql,qr):0)+(qr>hl?qsu(ORZ,ql,qr):0);}I int qmx(CI l,CI r,CI rt,CI ql,CI qr)//询问区间最大值{if(ql<=l&&r<=qr) return O[rt].Mx;RI hl=l+r>>1,t,res=-INF;return ql<=hl&&(t=qmx(STO,ql,qr),Gmax(res,t)),qr>hl&&(t=qmx(ORZ,ql,qr),Gmax(res,t)),res;}I int qmn(CI l,CI r,CI rt,CI ql,CI qr)//询问区间最小值{if(ql<=l&&r<=qr) return O[rt].Mn;RI hl=l+r>>1,t,res=INF;return ql<=hl&&(t=qmn(STO,ql,qr),Gmin(res,t)),qr>hl&&(t=qmn(ORZ,ql,qr),Gmin(res,t)),res;}public:I void Init(CI x,int* s) {for(RI i=1;i<=x;++i) v[i]=s[i];Build(1,n=x,1);}I void Update(CI x,CI y)//单点修改(这里使用非递归写法){RI l=1,r=n,rt=1,hl;W(l^r) hl=l+r>>1,x<=hl?(r=hl,rt<<=1):(l=hl+1,(rt<<=1)|=1);O[rt]=Interval(y,y,y);W(rt>>=1) PU(rt);}I int QSum(CI x,CI y) {return qsu(1,n,1,x,y);}I int QMax(CI x,CI y) {return qmx(1,n,1,x,y);}I int QMin(CI x,CI y) {return qmn(1,n,1,x,y);}
}T;
class ODT
{private:#define IT set<Il>::iterator#define ins insert#define era erase#define fir first#define LB lower_bound#define add(x) (!cnt[x]++&&++tot)#define del(x) (!--cnt[x]&&--tot)int cnt[N+5];struct Il//维护区间信息{int l,r,v;I Il(CI x=0,CI y=0,CI p=0):l(x),r(y),v(p){}I bool operator < (Con Il& t) Con {return l<t.l;}};set<Il> S;I IT Sp(CI x)//分裂操作{IT t;if((t=S.LB(Il(x)))!=S.end()&&!(t->l^x)) return t;RI l=(--t)->l,r=t->r,v=t->v;S.era(t),S.ins(Il(l,x-1,v));return S.ins(Il(x,r,v)).fir;}public:I void Init(CI x,int* s)//初始化节点信息 {for(RI i=(s[0]=s[x+1]=-1,1),t=0;i<=x+2;++i) s[i]^s[i-1]&&(S.insert(Il(t,i-1,s[i-1])),t=i);}I void Assign(CI x,CI y,CI v)//推平操作{IT tr=Sp(y+1),tl=Sp(x);S.era(tl,tr),S.ins(Il(x,y,v));}I int Q1(CI x,CI y)//处理第一种询问{if(!(c^1)) return T.QMin(x,y);//特判c=1memset(cnt,0,sizeof(cnt));IT tr=Sp(y+1),tl=Sp(x),ti=tl;RI t,res=INF,tot=0;//初始化W(ti!=tr) {add(ti->v);W(!(tot^c)) t=T.QSum(tl->r,ti->l),Gmin(res,t),del((tl++)->v);++ti;}//移动右端点,在保证颜色数量等于c的情况下才能移动左端点,然后在移动的同时更新答案return res==INF?-1:res;//判断是否无解,无解返回-1}I int Q2(CI x,CI y)//处理第二种询问{memset(cnt,0,sizeof(cnt));IT tr=Sp(y+1),tl=Sp(x),ti=tl;RI t,res=T.QMax(x,y);//初始化W(ti!=tr){++cnt[ti->v];W(ti!=tl&&cnt[ti->v]>1) --cnt[(tl++)->v];//不断移动左端点直至右端点所属颜色出现次数为1ti!=tl&&(t=T.QSum(tl->r,ti->l),Gmax(res,t));//更新答案if(ti->l^ti->r) W(ti!=tl) --cnt[(tl++)->v];++ti;//当出现右端点Size>1的情况,将左端点移动到右端点的位置上}return res;//返回答案}
}O;
int main()
{RI Qtot,i,op,x,y,z;for(F.read(n,Qtot,c),i=1;i<=n;++i) F.read(a[i]);T.Init(n,a);//读入数据for(i=1;i<=n;++i) F.read(a[i]);O.Init(n,a);W(Qtot--){switch(F.read(op,x,y),op)//处理操作{case 1:T.Update(x,y);break;case 2:F.read(z),O.Assign(x,y,z);break;case 3:F.writeln(O.Q1(x,y));break;case 4:F.writeln(O.Q2(x,y));break;}}return F.clear(),0;
}

转载于:https://www.cnblogs.com/chenxiaoran666/p/Luogu5251.html

【洛谷5251】[LnOI2019] 第二代图灵机(线段树+ODT)相关推荐

  1. 洛谷 - P1886 滑动窗口(单调队列/线段树)

    题目链接:点击查看 题目大意:给出一个由n个数构成的序列,再给出一个长度为k的窗口,这个窗口从第一个下标开始一直向后移动,每次移动一个单位,每次移动询问一次该窗口中的最大值和最小值,最后输出答案 题目 ...

  2. 【题解】洛谷P4145 花神游历各国(线段树)

    洛谷P4145:https://www.luogu.org/problemnew/show/P4145 思路 这道题的重点在于sqrt(1)=1 一个限制条件 与正常线段树不同的是区间修改为开方 那么 ...

  3. 洛谷P3960 列队(动态开节点线段树)

    题意 题目链接 Sol 看不懂splay..,看不懂树状数组... 只会暴力动态开节点线段树 观察之后不难发现,我们对于行和列需要支持的操作都是相同的:找到第\(k\)大的元素并删除,在末尾插入一个元 ...

  4. LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset

    题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...

  5. 洛谷 P4246 [SHOI2008]堵塞的交通 线段树

    题目描述 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个222行 C'>CCC列的矩形网格,网格上的每个点代表一个城市,相邻的城市 ...

  6. 洛谷P4839 P哥的桶 线段树+线性基

    传送门 题意:N个操作,第K个桶放一个X,查询L到R区间的桶任意数的异或最大值. P哥时不时地会找新女朋友,并把新找的女朋友丢进某个桶里面.我们用 1 k x 来表示P哥找了一个颜值为x的女朋友,并且 ...

  7. 洛谷P4837 养殖呆河马(线段树)

    题目描述 作为养殖场的大佬,阳阳引进了养殖呆河马的技术,而且她有一个团队来研究呆河马的养殖技巧来制定养殖规划,并在今年购入了 1 只呆河马.她们制定了从今年(即第 0 年)到第 n−1年的养殖呆河马的 ...

  8. ⌈洛谷1505⌋⌈BZOJ2157⌋⌈国家集训队⌋旅游【树链剖分】

    题目链接 [洛谷] [BZOJ] 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T ...

  9. 【JZOJ3794】【洛谷P1383】高级打字机【主席树】

    题目大意: 题目链接: 洛谷:https://www.luogu.org/problemnew/show/P1383 JZOJ:https://jzoj.net/senior/#main/show/3 ...

最新文章

  1. grape动态PHP结构(三)——API接口
  2. 「操作系统」《自己动手写操作系统》1.1前期准备工作
  3. 北京市常用和便民电话
  4. 计蒜客NOIP模拟赛(2) D2T2紫色百合
  5. Android studio | From Zero To One ——安装教程及前期学习总结
  6. 本地CDI限定词:@Any和@Default
  7. 2021-06-19 sklearn中的线性回归模型
  8. redis 多实例启动
  9. js面向对象的程序设计 --- 上篇(理解对象)
  10. 打造最快的Hash表
  11. 实战:小程序购物商城
  12. 毕业设计 基于单片机的智能蓝牙密码锁设计与实现
  13. Loadrunner脚本录制执行
  14. 网站如何被百度蜘蛛快速抓取?
  15. 爱荷华州立 计算机博士,2020年美国爱荷华州立大学博士全奖招生
  16. 怎么样去学习平面设计,学ps就是平面设计了吗?
  17. 谷歌浏览器无法使用谷歌翻译解决办法
  18. Unity编辑器下Console面板查看完整打印日志
  19. 使用 Cobertura 和反射机制提高 Java 单元测试中的代码覆盖率
  20. 最佳的75个安全工具

热门文章

  1. 单元测试instrumentation入门---eclipse
  2. 浅谈ASP.NET的Postback
  3. .NET完全手动搭建三层B/S架构
  4. Visual Studio原生开发的10个调试技巧
  5. 重构-改善既有代码的设计:简化条件表达式(七)
  6. 软件架构视图—4+1模式
  7. golang修改结构体中的切片值
  8. redis的key和value限制
  9. crackme之019
  10. maven WEB项目启动没问题访问页面就报错:org.apache.jasper.JasperException: Unable to compile class for JSP