HDU 5869.Different GCD Subarray Query-区间gcd+树状数组 (神奇的标记右移操作) (2016年ICPC大连网络赛)
树状数组。。。
Different GCD Subarray Query
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1541 Accepted Submission(s): 599
Given an array a of N positive integers a1,a2,⋯aN−1,aN; a subarray of a is defined as a continuous interval between a1 and aN. In other words, ai,ai+1,⋯,aj−1,aj is a subarray of a, for 1≤i≤j≤N. For a query in the form (L,R), tell the number of different GCDs contributed by all subarrays of the interval [L,R].
For each test, the first line consists of two integers N and Q, denoting the length of the array and the number of queries, respectively. N positive integers are listed in the second line, followed by Q lines each containing two integers L,R for a query.
You can assume that
1≤N,Q≤100000
1≤ai≤1000000
这个题的意思就是问区间内所有子段不同gcd的个数。
一开始理解错了题意,后来想明白了。假设区间的数为1 2 3 4
就是gcd(1),gcd(2),gcd(3),gcd(4),gcd(1,2),gcd(2,3),gcd(3,4),gcd(1,2,3),gcd(2,3,4),gcd(1,2,3,4)这些里面不同的gcd的个数是多少。
如果用在线算法操作,每查询一次就要处理依次数据,一方面会造成浪费,另一方面,你这样写妥妥的超时啊,所以要用离线算法,将所有的数据处理好之后,按顺序直接输出结果就可以。
首先用一个数组将数据保存起来,然后用一个vector数组将查询的区间和查询的顺序记录下来。
处理数据,就是相对来说固定右端点,从右往左移,在代码里就是对于每一个i(固定右端点),遍历一下i所在的子段的gcd,因为i不变,j是上一个i的gcd的值保存的顺序,j越大,i所在的子段就依次向左增加一个数,如果gcd发生了变化,就记录一下这个gcd以及出现的位置。可能越说越乱,画一个图表示一下。。。
图的意思就是假设数据为2 4 9 6 5,i为下标。假设i为4,就是固定4,然后遍历j,j存的是上一个i的子段的gcd,通过上一个i的gcd来得到i为4时(6)的子段的gcd,图中画的横线的长度就是子段的长度,橙色的矩形包含的长度是上一个i处理出的数据。就是固定右端点,依次往左遍历得到所有的gcd,这样不会重复操作,也不会漏掉某个子段。
将gcd整理出来之后,怎么操作才能使得区间查询的是不同的gcd的个数呢?
对于区间内相同的gcd,让标记gcd的下标尽量右移,找该gcd的最大右端点。
通过树状数组维护gcd的下标。
一边维护,一边查询树状数组就可以保证数据正确。
总结一下就是:固定右端点,依次往左找出来所有的gcd,并标记下标,因为是i逐渐增大的,所以后面遍历的时候也是相同gcd的最大右端点。直接查询就可以。
就这样吧,不想好好写了。
代码:
//离线处理-树状数组
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#include<utility>
using namespace std;
const int maxn=1e5+;
int Arr[maxn];//存数据一开始的值
int N,Q;
int pos[maxn*]; //记录gcd的位置
vector<pair<int ,int> >querys[maxn];
vector<pair<int, int> >gcds[maxn];
int ans[maxn];
int treeArr[maxn]; //树状数组 int gcd(int a,int b){ //gcd求最大公约数
if(!(a%b))return b;
else return gcd(b,a%b);
} void init(){ //初始化
int tmp,ts;
for(int i=;i<=N;i++){
tmp=Arr[i];
ts=i; //固定右端点,向左遍历
for(int j=;j<gcds[i-].size();j++){
int tmpgcd=gcd(tmp,gcds[i-][j].first);
if(tmpgcd!=tmp){ //如果gcd发生变化
gcds[i].push_back(make_pair(tmp,ts)); //first存gcd,second存gcd的左端点ts
ts=gcds[i-][j].second; //上一个gcd的右端点就是下一个gcd的左端点
tmp=tmpgcd;
}
}
gcds[i].push_back(make_pair(tmp,ts)); //将与上一个的最左端的gcd存起来
}
return;
} int lowbit(int x){ //取最低位的1
return x&(-x);
} void Add(int cur,int num){ //单点更新
for(int i=cur;i<=N;i+=lowbit(i))
treeArr[i]+=num; //由叶子节点向上更新树状数组
return;
} int Query(int cur){ //区间查询 从右端点往左加二进制最低位1的
int sum=;
for(int i=cur;i>;i-=lowbit(i))
sum+=treeArr[i];
return sum;
} void Solve(){
memset(pos,,sizeof(pos));
memset(treeArr,,sizeof(treeArr));
for(int i=;i<=N;i++){
for(int j=;j<gcds[i].size();j++){
if(pos[gcds[i][j].first]){ //如果标记已经存在,就将标记去掉,所以执行单点更新操作
Add(pos[gcds[i][j].first],-);
}
Add(gcds[i][j].second,);//一个新的不同的gcd,从叶子节点开始更新个数+1
pos[gcds[i][j].first]=gcds[i][j].second;//记录该gcd的右端点
}
for(int j=;j<querys[i].size();j++){
ans[querys[i][j].second]=Query(i)-Query(querys[i][j].first-);//区间右端点-区间左区间
}
}
for(int i=;i<=Q;i++)
printf("%d\n",ans[i]); return;
}
int main(){
//reopen("input","r",stdin);
while(~scanf("%d%d",&N,&Q)){
for(int i=;i<=N;i++){
scanf("%d",&Arr[i]); //将数据存在Arr数组中
querys[i].clear(); //清空
gcds[i].clear(); //清空
}
init();
int tmp1,tmp2;
for(int i=;i<=Q;i++){
scanf("%d%d",&tmp1,&tmp2);
querys[tmp2].push_back(make_pair(tmp1,i)); //将tmp1与i成对插入vector的tmp2下标里
}
Solve();
}
return ;
}
就这样吧,这题没什么,主要是想明白就很简单。
咸鱼太菜,学长要捶爆我的狗头吗???
已经做好了被学长打死的思想准备。。。
HDU 5869.Different GCD Subarray Query-区间gcd+树状数组 (神奇的标记右移操作) (2016年ICPC大连网络赛)的更多相关文章
- 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 5997 rausen loves cakes(启发式合并 + 树状数组统计答案)
题目链接 rausen loves cakes 题意 给出一个序列和若干次修改和查询.修改为把序列中所有颜色为$x$的修改为$y$, 查询为询问当前$[x, y]$对应的区间中有多少连续颜色段. ...
- 51nod_1199 树的先跟遍历+区间更新树状数组
题目是中文,所以不讲题意 做法顺序如下: 使用先跟遍历,把整棵树平铺到一维平面中 使用自己整的区间更新树状数组模板进行相关操作. http://www.cnblogs.com/rikka/p/7359 ...
- 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 5654 xiaoxin and his watermelon candy 离线树状数组 区间不同数的个数
xiaoxin and his watermelon candy 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5654 Description Du ...
- 【HDU4947】GCD Array(莫比乌斯反演+树状数组)
点此看题面 大致题意: 一个长度为\(n\)的数组,实现两种操作:将满足\(gcd(i,k)=d\)的\(a_i\)加上\(v\),询问\(\sum_{i=1}^xa_i\). 对于修改操作的推式子 ...
- hdu 1556:Color the ball(第二类树状数组 —— 区间更新,点求和)
Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- ACM学习历程—HDU5700 区间交(树状数组 && 前缀和 && 排序)
http://acm.hdu.edu.cn/showproblem.php?pid=5700 这是这次百度之星初赛2B的第五题.省赛回来看了一下,有这样一个思路:对于所有的区间排序,按左值排序. 然后 ...
- POJ 3321:Apple Tree + HDU 3887:Counting Offspring(DFS序+树状数组)
http://poj.org/problem?id=3321 http://acm.hdu.edu.cn/showproblem.php?pid=3887 POJ 3321: 题意:给出一棵根节点为1 ...
随机推荐
- 2017 ACM-ICPC EC-Final ShangHai(思维乱搞赛)
感觉全是思维乱搞题. Gym - 101775J Straight Master 给你n种扑克,你每次可以出连续的3 ~ 5 张,问你能否出完. Sample Input 2 13 1 2 2 1 0 ...
- eclipse中设置JVM内存
一. 修改jdk 使用内存: 找到eclispe 中window->preferences->Java->Installed JRE ,点击右侧的Edit 按钮,在编辑界面中的 ...
- A JavaScript Image Gallery
childNodes property: The childNodes property is a way of getting information about the children of ...
- 【PyTorch深度学习】学习笔记之PyTorch与深度学习
第1章 PyTorch与深度学习 深度学习的应用 接近人类水平的图像分类 接近人类水平的语音识别 机器翻译 自动驾驶汽车 Siri.Google语音和Alexa在最近几年更加准确 日本农民的黄瓜智能分 ...
- lambda表达式与函数接口的关系以及使用案例
lambda表达式与函数式接口是结合使用的. 函数式接口:接口中只有一个抽象方法的接口,其中可以包括default修饰,static 修饰的实例方法.函数式接口可以在接口上添加@FuncationIn ...
- loj6392 「THUPC2018」密码学第三次小作业 / Rsa
还是挺好做的,\((e_1,e_2)=1 \Rightarrow e_1s+e_2t=0\),\(m \equiv m^1 \equiv m^{e_1s+e_2t} \equiv c_1^s c_2^ ...
- python学习_常用语句
1.变量 1 name='hu qihang' #变量名应为英文,方便阅读 2 name_of_gf='chen ye' #多个单词用下划线隔开 3 名字='hu qihang' #变量名可以是中文 ...
- mvc-自定义Route
public class CustomerRoute : RouteBase { //从路径中解析出controller.action以及其他参数,创建RouteData(其中包括HttpHandle ...
- 整理 pycharm console调试博客
在Debug模式下,查看变量发现只能看到300个变量,报错: two large to show contents. Max items to show:300. 点击Debugger左侧consol ...
- [报错处理]Could not find a version that satisfies the requirement xml (from versions)
安装xml库发生报错 pip3 install xml Collecting xml Could not find a version that satisfies the requirement x ...