HDU 5869 Different GCD Subarray Query(2016大连网络赛 B 树状数组+技巧)
还是想不到,真的觉得难,思路太巧妙
题意:给你一串数和一些区间,对于每个区间求出区间内每段连续值的不同gcd个数(该区间任一点可做起点,此点及之后的点都可做终点)
首先我们可以知道每次添加一个值时gcd要么不变要么减小,并且减小的幅度很大,就是说固定右端点时最多只能有(log2 a)个不同的gcd,而且我们知道gcd(gcd(a,b),c)=gcd(a,gcd(b,c)),所以我们可以使用n*(log2 n)的时间预处理出每个固定右端点的不同gcd的值和位置。解法就是从左到右,每次只需要使用上一次的不同gcd的值和位置。
离线处理每个询问,按照区间右端点从小到大排序,把预处理的每个gcd依次加入树状数组中,这样到一个询问的右端点时就区间查询不同gcd的个数(只需要使用左端点的位置)。树状数组在每种gcd最右一个左端点的位置(贪心想法)存这儿gcd的个数,但可能这个gcd之前出现过,因此我们可以再开一个数组存每种gcd的位置(保证每种gcd在最右边的位置)
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=<<;
const double Pi=acos(-1.0);
const int Mod=1e9+;
const int Max=;
struct node
{
int mpos,gcd;
} dp[Max][]; //预处理
struct nide
{
int lef,rig,mpos;
} qes[Max];
int bit[Max],mpos[Max*];//树状数组处理此位置元素个数 某个gcd的位置(这时的最靠右)
int num[Max],ans[Max],n;
void Swap(int &a,int &b)
{
a^=b;
b^=a;
a^=b;
return;
}
int Gcd(int a,int b)// a、b 均为偶数, gcd(a,b) = 2 * gcd(a/2, b/2)
{
if(a<b)
Swap(a,b);
int c=; //a为偶数,b为奇数, gcd(a,b) = gcd(a/2 , b)
while(a-b) //a为奇数,b为偶数,gcd(a,b) = gcd(a, b/2)
{
if(a&) //a、b均为奇数, gcd(a,b) = gcd((a-b)/2, b)
{
if(b&)
{
if(a>b) a=(a-b)>>;
else b=(b-a)>>;
}
else b>>=;
}
else
{
if(b&) a>>=;
else c<<=,a>>=,b>>=;
}
}
return c*a;
}
int cntt[Max];
void Init()//预处理固定右端点时左边的g不通gcd
{
int tmp;
cntt[]=;
for(int i=; i<=n; ++i) //固定右端点i
{
cntt[i]=;
dp[i][].gcd=num[i];
dp[i][].mpos=i;
for(int j=; j<=cntt[i-]; ++j)
{
tmp=Gcd(dp[i][cntt[i]].gcd,dp[i-][j].gcd);
if(tmp!=dp[i][cntt[i]].gcd)//与每个右端点形成不同的gcd的位置要尽量靠右
{
dp[i][++cntt[i]].gcd=tmp;
dp[i][cntt[i]].mpos=dp[i-][j].mpos;
}
}
}
return;
}
bool cmp(struct nide p1,struct nide p2)//排序右端点才可以统计
{
return p1.rig<p2.rig;
}
int lowbit(int x)
{
return x&(-x);
}
void Add(int x,int y)
{
while(x<=n)
{
bit[x]+=y;
x+=lowbit(x);
}
return;
}
int Sum(int x)
{
int sum=;
while(x)
{
sum+=bit[x];
x-=lowbit(x);
}
return sum;
}
void Solve(int q)
{
memset(bit,,sizeof(bit));
memset(mpos,,sizeof(mpos));
int k=,sum=;
for(int i=; i<=n; ++i) //枚举右端点
{
for(int j=; j<=cntt[i]; ++j)
{
if(!mpos[dp[i][j].gcd])
{
sum++;
Add(dp[i][j].mpos,);
mpos[dp[i][j].gcd]=dp[i][j].mpos;
}
else if(mpos[dp[i][j].gcd]<dp[i][j].mpos)//保证最右位置
{
Add(mpos[dp[i][j].gcd],-);
Add(dp[i][j].mpos,);
mpos[dp[i][j].gcd]=dp[i][j].mpos;
}
}
while(k<=q&&qes[k].rig==i)
{
ans[qes[k].mpos]=sum-Sum(qes[k].lef-);//计算[lef,rig]的个数
++k;
}
}
return;
}
int main()
{
int q;
while(~scanf("%d %d",&n,&q))
{
for(int i=; i<=n; ++i)
scanf("%d",&num[i]);
Init();
for(int i=; i<=q; ++i)
{
scanf("%d %d",&qes[i].lef,&qes[i].rig);
qes[i].mpos=i;
}
sort(qes+,qes++q,cmp);
Solve(q);
for(int i=; i<=q; ++i)
printf("%d\n",ans[i]);
}
return ;
}
HDU 5869 Different GCD Subarray Query(2016大连网络赛 B 树状数组+技巧)的更多相关文章
- query 2019徐州网络赛(树状数组)
query \[ Time Limit: 2000 ms \quad Memory Limit: 262144 kB \] 题意 补题才发现比赛的时候读了一个假题意.... 给出长度为 \(n\) 的 ...
- HDU 5869 Different GCD Subarray Query rmq+离线+数状数组
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5869 Different GCD Subarray Query Time Limit: 6000/3 ...
- hdu 5869 Different GCD Subarray Query BIT+GCD 2016ICPC 大连网络赛
Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K ( ...
- HDU 5869 Different GCD Subarray Query (GCD种类预处理+树状数组维护)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5869 问你l~r之间的连续序列的gcd种类. 首先固定右端点,预处理gcd不同尽量靠右的位置(此时gc ...
- HDU 5869 Different GCD Subarray Query 树状数组 + 一些数学背景
http://acm.hdu.edu.cn/showproblem.php?pid=5869 题意:给定一个数组,然后给出若干个询问,询问[L, R]中,有多少个子数组的gcd是不同的. 就是[L, ...
- HDU 5869 Different GCD Subarray Query 离线+树状数组
Different GCD Subarray Query Problem Description This is a simple problem. The teacher gives Bob a ...
- HDU 5869 Different GCD Subarray Query 树状数组+离线
Problem Description This is a simple problem. The teacher gives Bob a list of problems about GCD (Gr ...
- HDU 5869 Different GCD Subarray Query
离线操作,树状数组,$RMQ$. 这个题的本质和$HDU$ $3333$是一样的,$HDU$ $3333$要求计算区间内不同的数字有几个. 这题稍微变了一下,相当于原来扫描到$i$的之后是更新$a[i ...
- 【刷题】HDU 5869 Different GCD Subarray Query
Problem Description This is a simple problem. The teacher gives Bob a list of problems about GCD (Gr ...
随机推荐
- Ubuntu 16.04下编译安装Apache2.4和PHP7结合
Ubuntu 16.04下编译安装Apache2.4和PHP7结合,并安装PDOmysql扩展. 1.编译安装apache2.4.20 1 第一步: ./configure --prefix=/usr ...
- 检测session用户信息跳转首页界面
方案一:采用jsp方式检测用户信息跳转 <%@ page language="java" pageEncoding="UTF-8"%> <%@ ...
- Mysql----mysql启动服务时提示"服务名无效"
1,首先说明一下我的环境,我刚开始是用的XAMPP这个集成的软件,里面安装了apache, mysql,tomcat这些软件,然后通过控制面板对其进行启动关闭的操作,这些操作很方便,但是我就用net ...
- shiro自定义logout filter
虽然shiro有自己默认的logout过滤器,但是,有些时候,我们需要自己定义一下操作,比如说loutgout后,进入指定页面,或者logout后写入日志操作,这个时候,我们可以通过自定义logout ...
- 10 Memcached 一致性哈希分布式算法原理与实现[PHP实现]
<?php header("Content-type:text/html;charset=utf-8"); interface hash{ public function _ ...
- shell遍历文件目录,监听文件变化,拼接字符串
最近利用业余时间学习了shell 并做了个例子 实现的功能是 : 监听demo文件夹下的文件,只要新增了 .js的文件就把对应的文件名重组,拼接, 最后写入到demo.js里面. 文件结构如下 : ...
- 由浅到深理解ROS(4)
消息和消息类型 节点能相互传递消息,节点之间通信也是基于消息.消息类型也就是数据类型数据类型,理解消息的类型很重要,因为它决定了消息的内容.也就是说,一个话题的消息类型能告诉你该话题中每个消息携带了哪 ...
- python入门课程 第一章 课程介绍
1-1 Python入门课程介绍特点: 优雅.明确.简单适合领域: web网站和各种网络服务 系统工具和脚本 作为"胶水"语言把其他语言开发的模块包装起来方 ...
- iOS main函数讲解
int main(int argc, char * argv[]) { @autoreleasepool { //四个参数 主要讲解后面两个参数 /* 第三个参数:UIApplication或者其子类 ...
- cocos2dx使用cocostudio导出的animation
local uilocal function createLayerUI() if not ui then ui=cc.Layer:create(); createLayerUI=nil; end r ...