Codeforces 848 C

题意:给\(n\)个数,\(m\)个询问,每一个询问有以下类型:

  • 1 p x:将第p位改成x。
  • 2 l r:求出\([l,r]\)区间中每一个出现的数的最后一次出现位置-第一次出现位置的和。

思路:我比较愚钝,只会最菜的\(O(n\times sqrt(n)\times log(n))\)的做法。

首先我们来想查询操作。我们将原序列分成B个一段,其中B是自己指定的。然后我们维护好所有的从第\(i\times B\)个到第\(j\times B-1\)个的数中的答案,然后把第\(l\)个到第\(i\times B-1\)个,第\(j\times B\)到第\(r\)个的数都重新计算位置,就求出了答案。

下面来搞超难弄的修改操作。我们把修改操作拆成先删除p位置的数,再将x插入到第p位中。

首先看删除。我们肯定要维护每一个数都在那些位置里面出现了。那么我们就设这个数在p之前的一次出现在prv位,后一次出现在nxt位。

然后我们看会有那些块的区间受到了影响。

首先我们看以0到prv之间为开始,now到nxt为结束的段,它们原来的答案是now-某个数,但现在变成了prv-某个数,所以减去了now-prv。

再看以prv到now之间为开始,nxt到n为结束的段,它们原来的答案是某个数-now,现在变成了某个数-nxt,减去了nxt-now。

所以就知道我们需要的是区间修改、单点查询的数据结构\(--bit\)。

然后就考虑添加。其实添加的操作和删除是正好反过来的,只用加上原来减去的数就可以了。

然后只是这么做是会WA在样例上的,因为我们没有特判如果没有nxt或者prv的情况。。。特判一下即可。。。

但是还是会TLE哒,我就T了好长好长时间。。。然后我调参,卡常。。。搞了半天才好不容易擦着时限过了。。。

2019年3月13日

Codeforces 848 C 分析

V--o_o--V:
首先我们考虑每隔一段时间把现在更新的所有内容集体更新一下。
然后因为每O(sqrt(N))次查询就更新不会使当前剩余没有更新的数太多,并且也不会更新太多次,所以就这样做。
集体更新的时候我们维护一个vals数组表示每一个数出现多少次,然后还有一个nvals表示没有被更新进去的数出现了多少次。
我们更新的时候只关注从当前开始下sqrt(N)次查询。
然后我们通过分块来求出所有的下sqrt(N)次查询的最大值和最小值:
对于最大值,我们从左向右扫描,不断加入新的数,设当前的数为a[i],上一次出现是在p[a[i]],那么我们原来说在p[a[i]]处a[i]最后一次出现,但现在需要将那一次出现删除,在i处增加一次出现位置。对于以i结尾的询问们,就可以通过分块处理的动态前缀和来求出这一个区间内最后一次出现的数的位置和。
对于最小值也是一样,不过从右向左扫描即可。
对于修改操作,我们只需要将当前修改的数通过插入排序放到一个chg序列里面即可。
对于查询操作,我们首先取更新时算出的最大出现和最小出现和,然后把至当前为止新加的更新都通过nvals来算出它们第一次出现位置和最后一次出现位置的差。

优化过程:
TLE6 -> TLE6:调了个sqrt(N)的参数(250 -> 317,然而并没有太大的用处),把cin改成了scanf(。。。)
TLE6 -> TLE7:增加了一些小的优化,比如将chg改成了数组(原来用的是vector),把vals改成了vector(原来是set)等。
TLE7 -> TLE7:这是一次测试用提交,他怕自己是因为O(log n)求某个数在[l,r]区间中的最早最晚出现的差的操作次数太多而超时的(但是他其实是每次重算nvals花了太多时间)
TLE7 -> AC:将树状数组改成了分块,并且将每次更新的时候重算的nvals改成了每一次查询就更改需要改的数(这个才是重点)

Reyna:
首先我们把所有的询问分成每sq个一组进行处理,其中sq为sqrt(N)
然后我们考虑从bg到ed的sq个询问怎么处理。这里其实和V--o__o--V的差不多,只是他没有分别求出每一个查询的区间中的每一个数出现的最早和最晚位置,而是直接用树状数组求出了所有数从第i位开始出现的最早位置-第一次出现位置的和。
然后也是从左向右扫描,不断加入新的数,然后对于查询(ql,qr)只需要求出sum(qr)-sum(ql-1)即可,因为最晚-最早是可以相减的:假设我们现在考虑x这个数,在[1,qr]中最后一次出现为i(因为是从左向右),在[ql,n]中第一次出现为j,[1,ql]中第一次出现为k,那么[ql,qr]的答案就是(i-k)-(j-k)=i-j。
最后再将这sq个中间的新加的更新都放到marked里面,暴力将这些都算出来加进答案中。

TimonKnigge:
树。。。树套树。。。
首先弄一棵zkw线段树,在每一个节点上是一棵Treap,其中存的内容是这一个区间内所有数最后一次出现-第一次出现的和。
我们考虑修改操作。首先我们需要将当前的这个数删掉再添加。
删除的时候就是我们把当前这个数的前后找出,记为pre和nxt,那么我们需要将原来这个数的在这个地方的出现删去,将这个数后一次出现的答案改成nxt-pre。
添加的时候也是差不多,把nxt的答案改成nxt-now,把now的答案改成now-pre即可。
那么查询的时候就是在线段树中找到需要查询的节点,把其中的>=l的部分都计入答案中即可。

SkyDec:
好像叫什么CDQ分治???
首先我们把所有的修改、查询询问按照时间排序,其中每一个修改操作都要变成删除(把nxt的答案改成nxt-pre)+添加(把now的答案改成now-pre,nxt的答案改成nxt-now),然后考虑前一半、后一半时间的修改对查询的影响,把他们合并,就是按照每一个操作的右端点排序,然后用bit维护每一个位置所对应的后缀中所有最后一次出现的数减去第一次出现的数的位置的和,然后按照右端点顺序从左向右扫描,对每一个求答案即可。

【Codeforces 848C】Goodbye Souvenir的更多相关文章

  1. 【codeforces 415D】Mashmokh and ACM(普通dp)

    [codeforces 415D]Mashmokh and ACM 题意:美丽数列定义:对于数列中的每一个i都满足:arr[i+1]%arr[i]==0 输入n,k(1<=n,k<=200 ...

  2. 【codeforces 707E】Garlands

    [题目链接]:http://codeforces.com/contest/707/problem/E [题意] 给你一个n*m的方阵; 里面有k个联通块; 这k个联通块,每个连通块里面都是灯; 给你q ...

  3. 【codeforces 707C】Pythagorean Triples

    [题目链接]:http://codeforces.com/contest/707/problem/C [题意] 给你一个数字n; 问你这个数字是不是某个三角形的一条边; 如果是让你输出另外两条边的大小 ...

  4. 【codeforces 709D】Recover the String

    [题目链接]:http://codeforces.com/problemset/problem/709/D [题意] 给你一个序列; 给出01子列和10子列和00子列以及11子列的个数; 然后让你输出 ...

  5. 【codeforces 709B】Checkpoints

    [题目链接]:http://codeforces.com/contest/709/problem/B [题意] 让你从起点开始走过n-1个点(至少n-1个) 问你最少走多远; [题解] 肯定不多走啊; ...

  6. 【codeforces 709C】Letters Cyclic Shift

    [题目链接]:http://codeforces.com/contest/709/problem/C [题意] 让你改变一个字符串的子集(连续的一段); ->这一段的每个字符的字母都变成之前的一 ...

  7. 【Codeforces 429D】 Tricky Function

    [题目链接] http://codeforces.com/problemset/problem/429/D [算法] 令Si = A1 + A2 + ... + Ai(A的前缀和) 则g(i,j) = ...

  8. 【Codeforces 670C】 Cinema

    [题目链接] http://codeforces.com/contest/670/problem/C [算法] 离散化 [代码] #include<bits/stdc++.h> using ...

  9. 【codeforces 515D】Drazil and Tiles

    [题目链接]:http://codeforces.com/contest/515/problem/D [题意] 给你一个n*m的格子; 然后让你用1*2的长方形去填格子的空缺; 如果有填满的方案且方案 ...

随机推荐

  1. 在WindowsPhone开发中使用MVVM设计模式

    相信.NET程序员多多少少都听说过MVVM的设计模式,对于一个大一点的项目来说,使用这种设计模式无疑是一种不错的选择, 它提高了程序的可维护性,降低了耦合度,可以实现代码的重用,方便独立开发和进行测试 ...

  2. HotSpot 虚拟机对象揭秘【转载】

    对象的创建 Java 对象的创建过程, ①类加载检查: 虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过.解 ...

  3. NIO 学习笔记一

    Java NIO 由以下几个核心部分组成: ChannelsBuffersSelectors Channel 和 Buffer 基本上,所有的 IO 在NIO 中都从一个Channel 开始.Chan ...

  4. js之搜索框

    目标效果:点击搜索框,搜索框内提示信息消失,可输入搜索信息,点击搜索框外搜索框如果没提示信息或者为空时,显示搜索框提示信息,如果有搜索信息,显示搜索信息. 代码如下: <!DOCTYPE htm ...

  5. layer.open

    1.type-基本层类型 类型:Number,默认:0 layer提供了5种层类型.可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层). 若你采用layer. ...

  6. 【代码笔记】Web-ionic-select

    一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  7. 用PHP去掉文件头的Unicode签名(BOM)

    <?php //此文件用于快速测试UTF8编码的文件是不是加了BOM,并可自动移除 //By Bob Shen $basedir="."; //修改此行为需要检测的目录,点表 ...

  8. Linux 磁盘分区方案简析

    Linux 磁盘分区方案简析 by:授客 QQ:1033553122   磁盘分区 任何硬盘在使用前都要进行分区.硬盘的分区有两种类型:主分区和扩展分区.一个硬盘上最多只能有4个主分区,其中一个主分区 ...

  9. 安卓界面之Toolbar+tablayout+viewpager仿WhatsApp界面样式

    实现界面: 布局代码: <?xml version="1.0" encoding="utf-8"?> <android.support.con ...

  10. Android-滑动解锁高亮文字自定义TextView

    public class HightLightTextView extends TextView { // 存储view的宽度 private int mTextViewWidth = 0; // 画 ...