还是想不到,真的觉得难,思路太巧妙

题意:给你一串数和一些区间,对于每个区间求出区间内每段连续值的不同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 树状数组+技巧)的更多相关文章

  1. query 2019徐州网络赛(树状数组)

    query \[ Time Limit: 2000 ms \quad Memory Limit: 262144 kB \] 题意 补题才发现比赛的时候读了一个假题意.... 给出长度为 \(n\) 的 ...

  2. HDU 5869 Different GCD Subarray Query rmq+离线+数状数组

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5869 Different GCD Subarray Query Time Limit: 6000/3 ...

  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 ( ...

  4. HDU 5869 Different GCD Subarray Query (GCD种类预处理+树状数组维护)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5869 问你l~r之间的连续序列的gcd种类. 首先固定右端点,预处理gcd不同尽量靠右的位置(此时gc ...

  5. HDU 5869 Different GCD Subarray Query 树状数组 + 一些数学背景

    http://acm.hdu.edu.cn/showproblem.php?pid=5869 题意:给定一个数组,然后给出若干个询问,询问[L, R]中,有多少个子数组的gcd是不同的. 就是[L, ...

  6. HDU 5869 Different GCD Subarray Query 离线+树状数组

    Different GCD Subarray Query Problem Description   This is a simple problem. The teacher gives Bob a ...

  7. HDU 5869 Different GCD Subarray Query 树状数组+离线

    Problem Description This is a simple problem. The teacher gives Bob a list of problems about GCD (Gr ...

  8. HDU 5869 Different GCD Subarray Query

    离线操作,树状数组,$RMQ$. 这个题的本质和$HDU$ $3333$是一样的,$HDU$ $3333$要求计算区间内不同的数字有几个. 这题稍微变了一下,相当于原来扫描到$i$的之后是更新$a[i ...

  9. 【刷题】HDU 5869 Different GCD Subarray Query

    Problem Description This is a simple problem. The teacher gives Bob a list of problems about GCD (Gr ...

随机推荐

  1. PyQt5 GUI Programming With Python 3.6 (一)

    PyQt5 PyQt5是一个基于强大的图形程式框架Qt5的python接口, 主要包含以下几个大类: ● QtCore ● QtGui ● QtWidgets ● QtMultimedia ● QtB ...

  2. linux命令的别名alias,unalias

    1. 别名 linux别名alias的作用: 1. 简化特别长得命令和參数 2. 对一些命令添加默认选项.提高安全性. 2. alias使用 [www@work sh]$ alias lm='ls - ...

  3. Linux下性能分析工具汇总

    来自:http://os.51cto.com/art/201104/253114.htm 本文讲述的是:CPU性能分析工具.Memory性能分析工具.I/O性能分析工具.Network性能分析工具. ...

  4. Exploiting CVE-2015-2509 /MS15-100 : Windows Media Center could allow remote code execution

    Exploiting CVE-2015-2509 /MS15-100 : Windows Media Center could allow remote code execution Trend Mi ...

  5. [译]GLUT教程 - 整合代码6

    Lighthouse3d.com >> GLUT Tutorial >> Extras >> The Code So Far VI 下面代码以窗体模式启动.你可以在 ...

  6. android 各版本的区别

    三.Android 6.x 新增运行时权限概念 Android6.0或以上版本,用户可以完全控制应用权限.当用户安装一个app时,系统默认给app授权部分基础权限,其他敏感权限,需要开发者自己注意,当 ...

  7. 反射机制,jvm,class类型

    [说明]这是上午完成的内容或者说是接触到的知识点,包括servlet简单的数据库连接,表格的显示需要用到的插件jstl,还有最最多的java反射原理的讲解 1)数据库的设计 2)编程中用到的知识点 3 ...

  8. 【BZOJ2728】[HNOI2012]与非 并查集+数位DP

    [BZOJ2728][HNOI2012]与非 Description Input 输入文件第一行是用空格隔开的四个正整数N,K,L和R,接下来的一行是N个非负整数A1,A2……AN,其含义如上所述.  ...

  9. nginx学习之简化安装篇(一)

    环境:CentOS 6.5 1. 安装依赖环境 [root@localhost ~]# yum install pcre-devel zlib-devel openssl-devel -y 2. 安装 ...

  10. effect request

    from bs4 import BeautifulSoup import os filepath = 'D:\\pymine\\clean\\spider_map\\baidu_map_html_fi ...