首页 > 其他分享 >CF1418G Three Occurrences 做题笔记

CF1418G Three Occurrences 做题笔记

时间:2023-06-24 09:36:36浏览次数:53  
标签:CF1418G mod2 mod1 int s2 s1 Three Occurrences 500005

题目链接

题意是输出所有区间满足其内部每个数要么出现 $3$ 次要么不出现的个数。

因为是区间,数量很多,发现贡献是可以抵消的,直接无脑预处理前缀的桶。

然后枚举左端点,统计答案,怎么处理呢?

疯狂地向右扩展,直到区间内有数字出现了 $3$ 次以上(这样是对的,待会儿证明,另外扩展到前一个就够了,不要到有数字出现了 $4$ 次)。

现在的区间内出现的数字都是 $3$ 次及以下了,接着看这个区间内有没有合适的前缀桶 $b$,$b$ 的每一项减去 $1\cdots l-1$ 这个前缀的桶 $c$,然后得到一个新的桶 $d$,如果 $d$ 内元素都是 $0$ 或 $3$,那么合法的答案就多了一个。

现在我们发现桶内的元素值已经不重要了,重要的是对 $3$ 取模的结果对吧?这样如果两个前缀桶 $b$ 和 $c$ 相减能构成答案,那么这两个桶的每一项元素就必定相同了吧。

如何维护两个桶是否相同呢?暴力还是行不通的,我们可以把它从高到低看成一个 $13331$ 进制的数(

这么大的数还是存不下啊,我们把它对一个质数取模就行了,然后再开一个桶维护前缀桶就能快速找到在给定的区间内与桶 $d$ 大概率相同的桶啦。

再来看下那个的证明,假设有个合法的区间 $l$ $r$,那么它中的所有元素出现个数一定小于等于 $3$,所以在以 $l$ 为左端点扩展时一定会扩展到 $r$ 了,所以一定会被统计到。

这样会不会重复统计呢?当然不会,我们把答案分左端点统计了啊。

然后单模数哈希过不了,写了双哈希。

#include <unordered_map>
#include <time.h>
#include <iostream>
#define int long long
using namespace std;
const int mod1 = 998244353, mod2 = 1000000009;
int n, l, r, ans;
int a[500005], s[500005], s1[500005], s2[500005];
int p1[500005], p2[500005];
unordered_map <int, int> b, w, b_;
signed main () {
    cin >> n;
    p1[0] = p2[0] = 1;
    for (int i = 1; i <= n; i ++) {
        p1[i] = p1[i - 1] * 13331 % mod1;
        p2[i] = p2[i - 1] * 13331 % mod2;
    }
    for (int i = 1; i <= n; i ++) cin >> a[i];
    for (int i = 1; i <= n; i ++) {
        ++ b[a[i] ];
        s1[i] = s1[i - 1] + p1[a[i] ];
        s2[i] = s2[i - 1] + p2[a[i] ];
        if (s1[i] >= mod1) s1[i] -= mod1;
        if (s2[i] >= mod2) s2[i] -= mod2;
        if (b[a[i] ] == 3) {
            b[a[i] ] = 0;
            s1[i] -= p1[a[i] ] * 3;
            s2[i] -= p2[a[i] ] * 3;
            s1[i] = ( (s1[i] % mod1) + mod1) % mod1;
            s2[i] = ( (s2[i] % mod2) + mod2) % mod2;
        }
        s[i] = s2[i] * 1000000011 + s1[i];
    }
    b.clear ();
    for (l = 1; l <= n; l ++) {
        while (1) {
            if (r != n && b_[a[r + 1] ] != 3) {
                ++ b_[a[++ r] ];
                ++ b[s[r] ];
            } else break;
        }
        ans += b[s[l - 1] ];
        -- b_[a[l] ];
        -- b[s[l] ];
    }
    cout << ans;
    return 0;
}

标签:CF1418G,mod2,mod1,int,s2,s1,Three,Occurrences,500005
From: https://www.cnblogs.com/Xy-top/p/17500678.html

相关文章

  • Three.js教程:高光网格材质Phong
    推荐:将NSDT场景编辑器加入你的3D工具链其他系列工具:NSDT简石数字孪生高光网格材质Phong高光网格材质MeshPhongMaterial和基础网格材质MeshBasicMaterial、漫反射网格材质MeshLambertMaterial一样都是网格模型的Mesh的材质。高光网格材质MeshPhongMaterial和漫反射网格材质Mesh......
  • Three.js教程:Threejs常见几何体简介
    推荐:将NSDT场景编辑器加入你的3D工具链其他系列工具:NSDT简石数字孪生Threejs常见几何体简介Three.js提供的几何体API很多,本节课先给大家介绍几个比较简单的案例,为后面的学习打下基础。你可以结合threejs文档,把下面动手把下面几何体相关代码全部测试一遍,并预览3D效果。//BoxG......
  • 每日一题力扣 1262 https://leetcode.cn/problems/greatest-sum-divisible-by-three/
    、 题解这道题目核心就算是要知道如果x%3=2的话,应该要去拿%3=1的数字,这样子才能满足%3=0贪心sum不够%3的时候,就减去余数为1的或者余数为2的需要注意两个余数为1会变成余数为2的,所以可能减去2个余数为1核心代码如下publicintmaxSumDivThreeOther(int[]nums){​  ......
  • Three.js教程:动画渲染循环
    推荐:将NSDT场景编辑器加入你的3D工具链其他系列工具:NSDT简石数字孪生动画渲染循环threejs可以借助HTML5的API请求动画帧window.requestAnimationFrame实现动画渲染。请求动画帧window.requestAnimationFrame//requestAnimationFrame实现周期性循环执行//requestAnimationF......
  • three.js 置换贴图 alpha贴图 的妙用 - 3D文字不引入字体文件
    实现将文字绘制到canvascanvas生成置换贴图alpha贴图将canvas转换成texture将texture贴到material修改shader将黑色背景区域去掉视频教程请移步b站canvas生成贴图classCanvas{canvas:HTMLCanvasElement=document.createElement("canvas");protectedctx:CanvasRen......
  • threejs-初识shader
    GLSL文件: importvertexGLSLfrom'./shaders/test1-patterns/vertex.glsl?raw' uniformmat4projectionMatrix;uniformmat4viewMatrix;uniformmat4modelMatrix;uniformvec2uFrequency;uniformfloatuTime;attributevec2uv;attributevec3po......
  • Three.js教程:相机控件轨道控制器OrbitControls
    推荐:将NSDT场景编辑器加入你的3D工具链其他系列工具:NSDT简石数字孪生相机控件轨道控制器OrbitControls平时开发调试代码,或者展示模型的时候,可以通过相机控件OrbitControls实现旋转缩放预览效果。OrbitControls使用你可以打开课件案例源码测试下效果。旋转:拖动鼠标左键缩放......
  • Three.js教程:三维坐标系
    推荐:将NSDT场景编辑器加入你的3D工具链其他系列工具:NSDT简石数字孪生三维坐标系本节课的目的就是为了加强大家对threejs三维空间的认识。辅助观察坐标系THREE.AxesHelper()的参数表示坐标系坐标轴线段尺寸大小,你可以根据需要改变尺寸。//AxesHelper:辅助观察的坐标系const......
  • Three.js教程:渲染器
    推荐:将NSDT场景编辑器加入你的3D工具链。其他系列工具:NSDT简石数字孪生渲染器生活中如果有了景物和相机,那么如果想获得一张照片,就需要你拿着相机,按一下,咔,完成拍照。对于threejs而言,如果完成“咔”这个拍照动作,就需要一个新的对象,也就是WebGL渲染器WebGLRenderer(opensnewwin......
  • Three.js教程:透视投影相机
    推荐:将NSDT场景编辑器加入你的3D工具链。其他系列工具:NSDT简石数字孪生Threejs如果想把三维场景Scene渲染到web网页上,还需要定义一个虚拟相机Camera,就像你生活中想获得一张照片,需要一台用来拍照的相机。透视投影相机PerspectiveCameraThreejs提供了正投影相机OrthographicCam......