Codeforces Round 969 (Div. 1) C. Eri and Expanded Sets(线段树维护差分数组gcd+双指针+尺取)

news2024/11/15 11:11:52

题目

转化一下题意就是,

给定一个n(n<=4e5),代表数组a的长度,

求有多少区间,满足区间内两两差分后得到的新数组的gcd∈{0,1}

实际t(t<=1e4)组样例,保证sumn不超过4e5

思路来源

乱搞ac+jiangly代码

题解

一个重要的性质是,

区间内从小到大排好序相邻两项两两差分的gcd,等于区间内不排序相邻两项两两差分的gcd

以下的代码1是用了这个性质的,所以直接维护相邻项gcd即可,比较好写

代码2是在权值线段树上强行排了一下序的,非常难写

双指针维护一下,

对于枚举的右端点r,满足区间[l,r]的相邻项差分数组的gcd=1的最靠右的l,

由于gcd只会缩成因子,所以对于所有<=l的位置x,[x,r]的gcd都是等于1的,直接ans+=l

具体代码里是,在[l,r]区间长度不短于2的前提下,试着把当前l往右挪一个,

只要gcd为1的话就可以一直往右挪,否则break,并往左回滚一个

特别地,gcd=0和gcd=1不能放在一起维护,否则不满足双指针的单调性了,所以这里分开统计的

gcd=0的段就是区间内所有值都相同的段,尺取即可

代码1

//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
const int N=4e5+10;
int t,n,a[N],l,r,kd;
int gcd(int x,int y){
    return !y?x:gcd(y,x%y);
}
struct segtree{
	int n;
	struct node{int l,r,v;}e[N<<2];
	#define l(p) e[p].l
	#define r(p) e[p].r
	#define v(p) e[p].v
	void up(int p){
        v(p)=gcd(v(p<<1),v(p<<1|1));
    }
	void bld(int p,int l,int r){
		l(p)=l;r(p)=r;v(p)=0;
		if(l==r){return;}
		int mid=l+r>>1;
		bld(p<<1,l,mid);bld(p<<1|1,mid+1,r);
		up(p);
	}
	void init(int _n){n=_n;bld(1,1,n);}
	void chg(int p,int x,int v){
		if(l(p)==r(p)){
            v(p)=v;
            return;
        }
		int mid=l(p)+r(p)>>1;
		chg(p<<1|(x>mid),x,v);
		up(p);
	}
    bool ok(){
        int x=v(1);
        if(!x)return 0;
        x-=x&(-x);
        return !x;
    }
}seg;
int main(){
    sci(t);
    while(t--){
        sci(n);
        rep(i,1,n){
            sci(a[i]);
        }
        seg.init(n);
        int l=1;
        ll ans=0;
        rep(r,2,n){//gcd=1的区间 满足x<=l的所有[x,r]
            seg.chg(1,r,abs(a[r]-a[r-1]));
            if(!seg.ok())continue;
            while(l+1<r && seg.ok()){
                seg.chg(1,l+1,0);
                l++;
                //printf("l:%d r:%d query:%d\n",l,r,seg.query());
            }
            //printf("l:%d r:%d query:%d\n",l,r,seg.query());
            if(!seg.ok()){
                seg.chg(1,l,abs(a[l]-a[l-1]));
                l--;
            }
            //printf("l:%d r:%d ok:%1d\n",l,r,seg.ok());
            ans+=l;
        }
        int p=0;
        rep(r,1,n){//gcd=0的区间 满足所有值都相同的区间
            if(r==1 || a[r]==a[r-1])p++;
            else ans+=1ll*p*(p+1)/2,p=1;
        }
        ans+=1ll*p*(p+1)/2;
        printf("%lld\n",ans);
    }
    return 0;
}

代码2(乱搞ac)

相当于给动态维护的区间[l,r]拍到一棵权值线段树上了,

并且需要维护每种数字出现的个数,和当前出现的数字的种类数,比较繁琐

#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
const int N=4e5+10;
int t,n,a[N],b[N],x[N],q[N],c,l,r,kd;
int gcd(int x,int y){
    return !y?x:gcd(y,x%y);
}
int LG(int n){
    return std::__lg(n);
    // int highestBit = 0;
    // while (n >>= 1) {
    //     highestBit++;
    // }
    // return highestBit;
}
struct segtree{
	int n;
	struct node{int l,r,v;}e[N<<2];
	#define l(p) e[p].l
	#define r(p) e[p].r
	#define v(p) e[p].v
	void up(int p){
        v(p)=gcd(v(p<<1),v(p<<1|1));
        //if(p==1)rep(i,1,17)printf("p:%d v:%d\n",i,v(i));
        //while(v(p) && v(p)%2==0)v(p)/=2;
    }
	void bld(int p,int l,int r){
		l(p)=l;r(p)=r;
        //printf("p:%d l:%d r:%d\n",p,l,r);
		if(l==r){v(p)=0;return;}
		int mid=l+r>>1;
		bld(p<<1,l,mid);bld(p<<1|1,mid+1,r);
		up(p);
	}
	void init(int _n){n=_n;bld(1,1,n);}
	void chg(int p,int x,int v){
		if(l(p)==r(p)){
            //if(v==410)printf("vvv");
            //while(v && v%2==0)v/=2;
            v(p)=v;return;
        }
		int mid=l(p)+r(p)>>1;
		chg(p<<1|(x>mid),x,v);
		up(p);
	}
	int cnt(int p,int ql,int qr){
		if(ql<=l(p)&&r(p)<=qr)return v(p);
		int mid=l(p)+r(p)>>1,res=0;
		if(ql<=mid)res|=cnt(p<<1,ql,qr);
		if(qr>mid)res|=cnt(p<<1|1,ql,qr);
		return res;
	}
    bool ok(){
        int x=v(1);
        x-=x&(-x);
        return !x;
    }
    int query(){
        return v(1);
    }
}seg;
struct BitPre{ // 求前缀和(可改为max等)
	int n,tr[N];
	void init(int _n){
		n=_n;
		memset(tr,0,(n+1)*sizeof(*tr));
	}
	void add(int x,int v){
		for(int i=x;i<=n;i+=i&-i)
		tr[i]+=v;
	}
	int sum(int x){
		int ans=0; 
		for(int i=x;i;i-=i&-i)
		ans+=tr[i];
		return ans;
	}
    int askp(int p){
        return sum(p)-sum(p-1);
    }
    // 树状数组求从小到大第k个, 1<=k<=sum(n), 1<=x<=n
    int kth(int k){
        int x=0;
        for(int i=1<<LG(n);i;i>>=1){
            if(x+i<=n && k>tr[x+i]){
                x+=i;
                k-=tr[x];
            }
        }
        return x+1;
    }
}tr;
void add(int r){
    if(!q[b[r]])kd++;q[b[r]]++;
    //printf("r:%d kd:%d\n",r,kd);
    //q.insert(r);
    tr.add(b[r],1);
    int pre=tr.sum(b[r]-1);
    if(pre){
        int w=tr.kth(pre);
        //if(r==5)printf("r:%d w:%d delta:%d\n",r,w,x[b[r]-1]-x[w-1]);
        seg.chg(1,b[r],x[b[r]-1]-x[w-1]);
    }
    int now=tr.sum(b[r]),all=tr.sum(c);
    //printf("r:%d now:%d all:%d\n",r,now,all);
    if(now<all){
        int w=tr.kth(now+1);
        //if(r==5)printf("r:%d w:%d delta:%d\n",r,w,x[w-1]-x[b[r]-1]);
        seg.chg(1,w,x[w-1]-x[b[r]-1]);
    }
}
void del(int r){
    q[b[r]]--;if(!q[b[r]])kd--;
    tr.add(b[r],-1);
    if(tr.askp(b[r]))return;
    seg.chg(1,b[r],0);
    int now=tr.sum(b[r]),all=tr.sum(c);
    //printf("del r:%d now:%d all:%d\n",r,now,all);
    if(now<all){
        int w=tr.kth(now+1);
        //printf("xw:%d br:%d\n",x[w-1],x[b[r]-1]);
        if(now){
            int pre=tr.kth(now);
            //printf("del l:%d now:%d all:%d w:%d\n",r,now,all,w,pre);
            seg.chg(1,w,x[w-1]-x[pre-1]);
        }
        else{
            //printf("del l:%d w:%d zero xw:%d\n",r,w,x[w-1]);
            seg.chg(1,w,0);
        }
    }
}
int main(){
    sci(t);
    while(t--){
        sci(n);
        c=0;kd=0;
        rep(i,1,n){
            sci(a[i]);
            q[i]=0;
            x[c++]=a[i];
        }
        sort(x,x+c);
        c=unique(x,x+c)-x;
        rep(i,1,n){
            b[i]=lower_bound(x,x+c,a[i])-x+1;
        }
        //rep(i,0,c-1)printf("i:%d x:%d\n",i+1,x[i]);
        tr.init(c);
        seg.init(c);
        int l=1;
        ll ans=0;
        // rep(r,1,n){
        //     vector<int>now;
        //     now.pb(x[b[r]-1]);
        //     per(l,r-1,1){
        //         now.pb(x[b[l]-1]);
        //         sort(now.begin(),now.end());
        //         int g=0,las=now[0];
        //         for(auto &v:now){
        //             g=gcd(g,v-las);
        //             las=v;
        //         }
        //         if(g==0 || g==1){
        //             printf("l:%d r:%d g:%d\n",l,r,g);
        //             break;
        //         }
        //     }
        // }
        rep(r,1,n){
            add(r);
            //printf("l:%d r:%d query:%d\n",l,r,seg.query());
            ///if(!seg.ok())continue;
            if(kd==1)continue;
            //printf("r:%d kd:%d\n",r,kd);
            if(!seg.ok())continue;
            while(kd>1 && seg.ok()){
                del(l);l++;
                //printf("l:%d r:%d query:%d\n",l,r,seg.query());
            }
            //printf("l:%d r:%d query:%d\n",l,r,seg.query());
            if(kd==1 || !seg.ok())add(--l);
            //printf("l:%d r:%d query:%d\n",l,r,seg.query());
            ans+=l;
        }
        int p=0;
        rep(r,1,n){
            if(r==1 || a[r]==a[r-1])p++;
            else ans+=1ll*p*(p+1)/2,p=1;
        }
        ans+=1ll*p*(p+1)/2;
        printf("%lld\n",ans);
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2156724.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C/C++内存管理 ——

目录 五、C/C内存管理 1、C/C内存分布 2、C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free 3、C内存管理方式 1.new/delete操作内置类型 2.new和delete操作自定义类型 4、operator new与operator delete函数 5、new和delete的实现原理 1.内置类…

SSM框架学习(四、SpringMVC实战:构建高效表述层框架)

目录 一、SpringMVC简介和体验 1.介绍 2.主要作用 3.核心组件和调用流程理解 4.快速体验 二、SpringMVC接收数据 1.访问路径设置 &#xff08;1&#xff09;精准路径匹配 &#xff08;2&#xff09;模糊路径匹配 &#xff08;3&#xff09;类和方法上添加 RequestMapp…

CSP-J 2024 入门组初赛第一轮初赛试题及答案解析

CSP-J 2024 入门组初赛第一轮初赛试题及答案解析 一、 单项选择题&#xff08;共15题&#xff0c;每题2分&#xff0c;共计30分&#xff1a;每题有且仅有一个正确选项&#xff09; 1 32 位 int 类型的存储范围是&#xff08; &#xff09; A -2147483647 ~ 2147483647 B -21…

【QGIS入门实战精品教程】6.1:QGIS根据属性条件查询数据(SQL表达式)

文章目录 一、字段过滤二、高级过滤(表达式)一、字段过滤 对于单个字段的查询,可以采用字段过滤,例如,从县区数据中,根据NAME字段,查找出县级市玉门市。操作为:右键县区→打开属性表: 点击左下角,选择name字段。 输入玉门市,回车,选择查找除的属性表记录,此时图斑…

汽车总线之----FlexRay总线

Introduction 随着汽车智能化发展&#xff0c;车辆开发的ECU数量不断增加&#xff0c;人们对汽车系统的各个性能方面提出了更高的需求&#xff0c;比如更多的数据交互&#xff0c;更高的传输带宽等。现如今人们广泛接受电子功能来提高驾驶安全性&#xff0c;像ABS防抱死系统&a…

计算机毕业设计之:基于深度学习的路面检测系统(源码+部署文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

【redis-02】深入理解redis中RBD和AOF的持久化

redis系列整体栏目 内容链接地址【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325【二】redis的持久化机制和原理https://zhenghuisheng.blog.csdn.net/article/details/142441756 如需转载&#xff0c;请输入&#xff1a;htt…

2025校招内推-招联金融

【投递方式】 直接扫下方二维码&#xff0c;或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus&#xff0c;使用内推码 igcefb 投递&#xff09; 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…

CentOS Stream 9部署docker,并开启API

1、安装docker &#xff08;1&#xff09;安装Docker的依赖项和存储库 sudo dnf install -y dnf-plugins-core sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo &#xff08;2&#xff09;安装Docker sudo dnf install -y docke…

0基础学习PyTorch——最小Demo

大纲 环境准备安装依赖 训练和推理训练生成数据加载数据TensorDatasetDataLoader 定义神经网络定义损失函数和优化器训练模型 推理 参考代码 PyTorch以其简洁直观的API、动态计算图和强大的社区支持&#xff0c;在学术界和工业界都享有极高的声誉&#xff0c;成为许多深度学习爱…

yum 集中式安装 LNMP

目录 安装 nginx 安装 mysql 安装 php 配置lnmp 配置 nginx 支持 PHP 解析 安装 nginx 修改yum源 将原本的yum源备份 vim /etc/yum.repos.d/nginx.repo [nginx-stable] namenginx stable repo baseurlhttp://nginx.org/packages/centos/7/$basearch/ gpgcheck0 enable…

黎巴嫩BP机爆炸事件启示录:我国应加快供应链安全立法

据报道&#xff0c;当地时间9月17日下午&#xff0c;黎巴嫩首都贝鲁特以及黎巴嫩东南部和东北部多地都发生了BP机爆炸事件。当时的统计数据显示&#xff0c;爆炸造成9人死亡&#xff0c;约2800人受伤。9月18日&#xff0c;死亡人数上升到11人&#xff0c;受伤人数超过4000。 目…

14年数据结构

第一题 解析&#xff1a; 求时间复杂度就是看程序执行了多少次。 假设最外层执行了k次&#xff0c;我们看终止条件是kn&#xff0c;则&#xff1a; 有, 内层是一个j1到jn的循环&#xff0c;显然执行了n次。 总的时间复杂度是内层外层 答案选C。 第二题 解析&#xff1a; 一步一…

车辆行人转向意图状态检测系统源码分享

车辆行人转向意图状态检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of …

【Python】Maya:为人类打造的 Python 日期时间库

不知道少了什么&#xff0c;总感觉没有以前快乐。 在编程中处理日期和时间总是一个挑战&#xff0c;尤其是当涉及到时间和时区的转换时。Maya 是一个由 Kenneth Reitz 开发的 Python 库&#xff0c;旨在简化日期时间的处理&#xff0c;使其对人类开发者更加友好。本文将介绍 M…

如何在jupyter notebook中使用虚拟环境

一&#xff1a;在cmd中打开已经创建好的虚拟环境 二&#xff1a;安装ipykernel conda install ipykernel 三&#xff1a;安装牛逼conda conda install -c conda-forge nb_conda 四&#xff1a;运行jupyter notebook,选择虚拟环境

linux强制关闭再启动后zookeeper无法启动

1、若开启了zkserver就先关闭zkserver 查看zkserver是否启动 sh zkServer.sh status关闭zkServer sh zkServer.sh stop2、更改conf/zoo.cfg 将这里的启动端口改为2183 3、启动zkServer sh zkServer.sh start4、以2183端口启动zkCli zkCli.sh -server 127.0.0.1:2183这样启…

传知代码-基于多尺度动态卷积的图像分类

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 概述 在计算机视觉领域&#xff0c;图像分类是非常重要的任务之一。近年来&#xff0c;深度学习的兴起极大提升了图像分类的精度和效率。本文将介绍一种基于动态卷积网络&#xff08;Dynamic Convolutional Netw…

机器人机构、制造

简单整理一下&#xff0c;在学习了一些运动学和动力学之类的东西&#xff0c;简单的整合了一些常用的机械结构和图片。 1.电机&#xff1a; 市面上的电机有&#xff1a;直流电机&#xff0c;交流电机&#xff0c;舵机&#xff0c;步进电机&#xff0c;电缸&#xff0c;无刷电…

【无人机设计与控制】 基于matlab的蚁群算法优化无人机uav巡检

摘要 本文使用蚁群算法&#xff08;ACO&#xff09;优化无人机&#xff08;UAV&#xff09;巡检路径。无人机巡检任务要求高效覆盖特定区域&#xff0c;以最小化能源消耗和时间。本研究提出的算法通过仿生蚁群算法优化巡检路径&#xff0c;在全局搜索和局部搜索中平衡探索与开…