点此看题面

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

\(ODT\)维护颜色

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

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

线段树维护数字和

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

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

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

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

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

处理询问

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

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

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

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

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

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

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

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

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

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

大致就是这些吧。

代码

  1. #include<bits/stdc++.h>
  2. #define Tp template<typename Ty>
  3. #define Ts template<typename Ty,typename... Ar>
  4. #define Reg register
  5. #define RI Reg int
  6. #define Con const
  7. #define CI Con int&
  8. #define I inline
  9. #define W while
  10. #define N 100000
  11. #define INF 1e9
  12. #define Gmax(x,y) (x<(y)&&(x=(y)))
  13. #define Gmin(x,y) (x>(y)&&(x=(y)))
  14. using namespace std;
  15. int n,c,a[N+5];
  16. class FastIO
  17. {
  18. private:
  19. #define FS 100000
  20. #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
  21. #define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
  22. #define tn (x<<3)+(x<<1)
  23. #define D isdigit(c=tc())
  24. int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
  25. public:
  26. I FastIO() {A=B=FI;}
  27. Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
  28. Tp I void write(Ty x) {x<0&&(pc('-'),x=-x);W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
  29. Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
  30. Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
  31. I void clear() {fwrite(FO,1,C,stdout),C=0;}
  32. }F;
  33. class SegmentTree//线段树
  34. {
  35. private:
  36. #define STO l,hl,rt<<1
  37. #define ORZ hl+1,r,rt<<1|1
  38. #define PU(x) (O[x]=O[x<<1]+O[x<<1|1])
  39. int n,v[N+5];
  40. struct Interval//维护区间信息
  41. {
  42. int S,Mx,Mn;I Interval(CI s=0,CI mx=-INF,CI mn=INF):S(s),Mx(mx),Mn(mn){}
  43. I Interval operator + (Con Interval& t) Con {return Interval(S+t.S,max(Mx,t.Mx),min(Mn,t.Mn));}
  44. }O[N<<2];
  45. I void Build(CI l,CI r,CI rt)//建树
  46. {
  47. if(!(l^r)) return (void)(O[rt]=Interval(v[l],v[l],v[l]));
  48. RI hl=l+r>>1;Build(STO),Build(ORZ),PU(rt);
  49. }
  50. I int qsu(CI l,CI r,CI rt,CI ql,CI qr)//询问区间和
  51. {
  52. if(ql<=l&&r<=qr) return O[rt].S;RI hl=l+r>>1;
  53. return (ql<=hl?qsu(STO,ql,qr):0)+(qr>hl?qsu(ORZ,ql,qr):0);
  54. }
  55. I int qmx(CI l,CI r,CI rt,CI ql,CI qr)//询问区间最大值
  56. {
  57. if(ql<=l&&r<=qr) return O[rt].Mx;RI hl=l+r>>1,t,res=-INF;
  58. return ql<=hl&&(t=qmx(STO,ql,qr),Gmax(res,t)),qr>hl&&(t=qmx(ORZ,ql,qr),Gmax(res,t)),res;
  59. }
  60. I int qmn(CI l,CI r,CI rt,CI ql,CI qr)//询问区间最小值
  61. {
  62. if(ql<=l&&r<=qr) return O[rt].Mn;RI hl=l+r>>1,t,res=INF;
  63. return ql<=hl&&(t=qmn(STO,ql,qr),Gmin(res,t)),qr>hl&&(t=qmn(ORZ,ql,qr),Gmin(res,t)),res;
  64. }
  65. public:
  66. I void Init(CI x,int* s) {for(RI i=1;i<=x;++i) v[i]=s[i];Build(1,n=x,1);}
  67. I void Update(CI x,CI y)//单点修改(这里使用非递归写法)
  68. {
  69. 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);
  70. O[rt]=Interval(y,y,y);W(rt>>=1) PU(rt);
  71. }
  72. I int QSum(CI x,CI y) {return qsu(1,n,1,x,y);}
  73. I int QMax(CI x,CI y) {return qmx(1,n,1,x,y);}
  74. I int QMin(CI x,CI y) {return qmn(1,n,1,x,y);}
  75. }T;
  76. class ODT
  77. {
  78. private:
  79. #define IT set<Il>::iterator
  80. #define ins insert
  81. #define era erase
  82. #define fir first
  83. #define LB lower_bound
  84. #define add(x) (!cnt[x]++&&++tot)
  85. #define del(x) (!--cnt[x]&&--tot)
  86. int cnt[N+5];
  87. struct Il//维护区间信息
  88. {
  89. int l,r,v;I Il(CI x=0,CI y=0,CI p=0):l(x),r(y),v(p){}
  90. I bool operator < (Con Il& t) Con {return l<t.l;}
  91. };set<Il> S;
  92. I IT Sp(CI x)//分裂操作
  93. {
  94. IT t;if((t=S.LB(Il(x)))!=S.end()&&!(t->l^x)) return t;
  95. RI l=(--t)->l,r=t->r,v=t->v;S.era(t),S.ins(Il(l,x-1,v));
  96. return S.ins(Il(x,r,v)).fir;
  97. }
  98. public:
  99. I void Init(CI x,int* s)//初始化节点信息
  100. {
  101. for(RI i=(s[0]=s[x+1]=-1,1),t=0;i<=x+2;++i)
  102. s[i]^s[i-1]&&(S.insert(Il(t,i-1,s[i-1])),t=i);
  103. }
  104. I void Assign(CI x,CI y,CI v)//推平操作
  105. {
  106. IT tr=Sp(y+1),tl=Sp(x);S.era(tl,tr),S.ins(Il(x,y,v));
  107. }
  108. I int Q1(CI x,CI y)//处理第一种询问
  109. {
  110. if(!(c^1)) return T.QMin(x,y);//特判c=1
  111. memset(cnt,0,sizeof(cnt));IT tr=Sp(y+1),tl=Sp(x),ti=tl;RI t,res=INF,tot=0;//初始化
  112. W(ti!=tr) {add(ti->v);W(!(tot^c)) t=T.QSum(tl->r,ti->l),Gmin(res,t),del((tl++)->v);++ti;}//移动右端点,在保证颜色数量等于c的情况下才能移动左端点,然后在移动的同时更新答案
  113. return res==INF?-1:res;//判断是否无解,无解返回-1
  114. }
  115. I int Q2(CI x,CI y)//处理第二种询问
  116. {
  117. memset(cnt,0,sizeof(cnt));IT tr=Sp(y+1),tl=Sp(x),ti=tl;RI t,res=T.QMax(x,y);//初始化
  118. W(ti!=tr)
  119. {
  120. ++cnt[ti->v];W(ti!=tl&&cnt[ti->v]>1) --cnt[(tl++)->v];//不断移动左端点直至右端点所属颜色出现次数为1
  121. ti!=tl&&(t=T.QSum(tl->r,ti->l),Gmax(res,t));//更新答案
  122. if(ti->l^ti->r) W(ti!=tl) --cnt[(tl++)->v];++ti;//当出现右端点Size>1的情况,将左端点移动到右端点的位置上
  123. }return res;//返回答案
  124. }
  125. }O;
  126. int main()
  127. {
  128. 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);//读入数据
  129. for(i=1;i<=n;++i) F.read(a[i]);O.Init(n,a);W(Qtot--)
  130. {
  131. switch(F.read(op,x,y),op)//处理操作
  132. {
  133. case 1:T.Update(x,y);break;case 2:F.read(z),O.Assign(x,y,z);break;
  134. case 3:F.writeln(O.Q1(x,y));break;case 4:F.writeln(O.Q2(x,y));break;
  135. }
  136. }return F.clear(),0;
  137. }

【洛谷5251】[LnOI2019] 第二代图灵机(线段树+ODT)的更多相关文章

  1. 【题解】Luogu P5251 [LnOI2019]第二代图灵机

    原题传送门 前置芝士:珂朵莉树 珂朵莉树的主要功能是区间赋值 这道题还算明显(操作2) 一开始看见这题觉得很毒瘤,但仔细想想发现颜色和数字之间没有什么关系 我们一共要维护三个东西: 1.区间和:树状数 ...

  2. 洛谷P3928 Sequence2(dp,线段树)

    题目链接: 洛谷 题目大意在描述底下有.此处不赘述. 明显是个类似于LIS的dp. 令 $dp[i][j]$ 表示: $j=1$ 时表示已经处理了 $i$ 个数,上一个选的数来自序列 $A[0]$ 的 ...

  3. 洛谷P3434 [POI2006]KRA-The Disks(线段树)

    洛谷题目传送门 \(O(n)\)的正解算法对我这个小蒟蒻真的还有点思维难度.洛谷题解里都讲得很好. 考试的时候一看到300000就直接去想各种带log的做法了,反正不怕T...... 我永远只会有最直 ...

  4. 洛谷.3733.[HAOI2017]八纵八横(线性基 线段树分治 bitset)

    LOJ 洛谷 最基本的思路同BZOJ2115 Xor,将图中所有环的异或和插入线性基,求一下线性基中数的异或最大值. 用bitset优化一下,暴力的复杂度是\(O(\frac{qmL^2}{w})\) ...

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

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

  6. 洛谷P4588 [TJOI2018]数学计算 【线段树】

    题目链接 洛谷P4588 题解 用线段树维护即可 #include<algorithm> #include<iostream> #include<cstring> ...

  7. 【洛谷3822】[NOI2017] 整数(线段树压位)

    题目: 洛谷 3822 分析: 直接按题意模拟,完了. 将每次加 / 减拆成不超过 \(32\) 个对单独一位的加 / 减. 考虑给一个二进制位(下称「当前位」)加 \(1\) 时,如果这一位本来就是 ...

  8. 洛谷P4556 雨天的尾巴(线段树合并)

    洛谷P4556 雨天的尾巴 题目链接 题解: 因为一个点可能存放多种物品,直接开二维数组进行统计时间.空间复杂度都不能承受.因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一 ...

  9. 洛谷P1712 [NOI2016]区间 尺取法+线段树+离散化

    洛谷P1712 [NOI2016]区间 noi2016第一题(大概是签到题吧,可我还是不会) 链接在这里 题面可以看链接: 先看题意 这么大的l,r,先来个离散化 很容易,我们可以想到一个结论 假设一 ...

随机推荐

  1. 1.1 Rust安装

    从今天起,坚持每天学习10分钟Rust...这是一个刚兴起几年的语言,希望深入地进行学习,为什么呢,因为以下这些让人辛酸的理由..... 最开始学习的是C++,没学太懂,之后又学了C,这时还完全对计算 ...

  2. java——newInstance()方法和new关键字

    https://www.cnblogs.com/liuyanmin/p/5146557.html 这两个都可以创建一个对象,那么这样个东西有什么不一样呢?什么时候用new,什么时候用newInstan ...

  3. math.random()方法的使用

    一:导言 以前总是被数字的范围正则搞的头大,在此总结了一下 二:用法 Math.random()函数返回0和1之间的伪随机数,可能为0,但总是小于1,[0,1) 生成n-m,包含n但不包含m的整数: ...

  4. mysql 死锁解决办法

    查询表的时候,发现一圈圈转啊转,就是不出来数据,猜测表被锁住 解决办法 : mysql> show processlist ; mysql> kill 4;       说明 : 4为 i ...

  5. 使用Xshell连接服务器

    转载原地址:http://www.server110.com/linux/201308/830.html 1)关于Xshell 网上更多的资料里提到的SSH客户端是putty,因为简单.开源.免费.但 ...

  6. pat06-图4. Saving James Bond - Hard Version (30)

    06-图4. Saving James Bond - Hard Version (30) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作 ...

  7. c++ 面试整理

    1. 继承方式 public    父类的访问级别不变 protected    父类的public成员在派生类编程protected,其余的不变 private        父类的所有成员变成pr ...

  8. HDU 4359——Easy Tree DP?——————【dp+组合计数】

    Easy Tree DP? Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  9. Hive总结

    一.什么是Hive 1.Hive 由 Facebook 实现并开源 2.是基于 Hadoop 的一个数据仓库 3.可以将结构化的数据映射为一张数据库表 4.并提供 HQL(Hive SQL)查询功能 ...

  10. 将php代码部署到新浪云测试(简单方法,包含数据库的连接)

    很多人做项目都是先在本地测试然后上传到服务器运行,如果包含了操作数据库的信息往往需要进行一番调试,这里我总结一下把php代码包含数据库的连接如何上传到新浪云服务器的步骤. 1.在新浪云应用SAE的控制 ...