HDU 5875 Function (线段树+gcd / 单调栈)
题意:给你一串数a再给你一些区间(lef,rig),求出a[lef]%a[lef+1]...%a[rig]
题解:我们可以发现数字a对数字b取模时:如果a<b,则等于原数,否则a会变小至少一半。就是说a最多成功取模(log2 a)次,所以我们只需要每次在区间内找到最前面一个小于等于a的值,接着更新a与区间左端点,直到没有值比a小或者区间取模完成。
我们可以使用线段树求出区间内小于某个值的最前一个位置,具体方法就是:父节点记录区间最小值,接着当这一整段的最小值小于等于给定的值时就递归进此子树(另一棵子树还是可能递归,因为可能前一个子树包含的区间大于所求的区间),这样我们知道第一次递归到叶子节点时就一定是最前一个小于等于此值的位置(如果有这个值的话)。
//别人的代码,自己还没写
#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=<<;
int nnum[Max],cnt,flag;
int segtr[Max];
struct node
{
int mmin,mpos;
}res;
void Upnow(int now,int next)
{
segtr[now]=min(segtr[next],segtr[next|]);
return;
}
void Create(int sta,int enn,int now)
{
if(sta==enn)
{
scanf("%d",&segtr[now]);
nnum[cnt++]=segtr[now];//记录每个位置的值
return;
}
int mid=dir(sta+enn,);
int next=mul(now,);
Create(sta,mid,next);
Create(mid+,enn,next|);
Upnow(now,next);
return;
}
void Query(int sta,int enn,int now,int x,int y,int z)
{
if(sta>=x&&enn<=y)
{
if(sta==enn)//到叶子节点
{
flag=;//表示只能到一次叶子节点
if(segtr[now]<=z)//找到
{
res.mmin=segtr[now];
res.mpos=sta;
}
return;
}
if(segtr[now]>z)//这一段不需要再递归
return;
}
int mid=dir(sta+enn,);
int next=mul(now,);
if(mid>=x&&!flag&&segtr[next]<=z)//之前没到叶子,子树区间最小值小于等于给定的值
Query(sta,mid,next,x,y,z);
if(mid<y&&!flag&&segtr[next|]<=z)
Query(mid+,enn,next|,x,y,z);
return;
}
int main()
{
int t,n,m;
int lef,rig;
scanf("%d",&t);
while(t--)
{
cnt=;
scanf("%d",&n);
Create(,n,);
scanf("%d",&m);
for(int i=;i<=m;++i)
{
scanf("%d %d",&lef,&rig);
if(lef==rig)//只有一个值
{
printf("%d\n",nnum[lef]);
continue;
}
int ans=nnum[lef];
lef++;
while()
{
res.mmin=Inf,res.mpos=-;
flag=;
Query(,n,,lef,rig,ans);
if(ans>=res.mmin)//成功取模
{
ans=ans%res.mmin;
lef=res.mpos+;
}
else
break;
if(lef>rig||ans==)//结束条件
break;
}
printf("%d\n",ans);
}
}
return ;
}
单调栈写法
/*#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std; int b[100005*4];
long long a[100005];
int c,l,r; void build(int node,int left,int right)
{
if(left==right)
{
scanf("%d",&b[node]);
a[c++]=b[node];
return;
}
build(node*2,left,(left+right)/2);
build(node*2+1,(left+right)/2+1,right);
b[node]=min(b[node*2],b[node*2+1]);
return;
} long long query(int x,int y,int left,int right,int node,int val)
{
if(x==y)
{
if (b[node]<=val) return left;
else return -1;
}
int mid = (left+right)/2;
int ans=-1;
if(x<=mid && b[node*2]<=val)
{
ans=query(x,y,left,mid,node*2,val);
return ans;
}
if(y>mid && b[node*2+1]<=val)
{
ans=query(x,y,mid+1,right,node*2+1,val);
return ans;
}
return -1;
} //以上是自己写的线段树,错误多多 int main()
{
int T,n,m;
long long ans;
while(~scanf("%d",&T))
{
while(T--)
{
scanf("%d",&n);
c=1;
build(1,1,n);
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&l,&r);
ans=a[l];
while(l<r)
{
l=query(l+1,r,1,n,1,a[l]);
if (l==-1) break;
ans=ans%a[l];
}
printf("%lld\n",ans);
}
}
}
return 0;
}
*/ #include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std; int a[],b[]; int main()
{
int T,n,m,l,r;
int ans;
while(~scanf("%d",&T))
{
while(T--)
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<=n;i++)
{
b[i]=-;
for(int j=i+;j<=n;j++)
if (a[j]<=a[i]) {b[i]=j;break;}
}
// for(int i=1;i<=n;i++) printf("%d ",b[i]);
// printf("\n");
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&l,&r);
ans=a[l];
while(l<r)
{
if(b[l]==- || b[l]>r) break;
ans=ans%a[b[l]];
l=b[l];
}
printf("%d\n",ans);
}
}
}
return ;
}
HDU 5875 Function (线段树+gcd / 单调栈)的更多相关文章
- [CSP-S模拟测试]:陶陶摘苹果(线段树维护单调栈)
题目传送门(内部题116) 输入格式 第一行两个整数$n,m$,如题 第二行有$n$个整数表示$h_1-h_n(1\leqslant h_i\leqslant 10^9)$ 接下来有$m$行,每行两个 ...
- Wannafly挑战赛18 E 极差(线段树、单调栈)
Wannafly挑战赛18 E 极差 题意 给出三个长度为n的正整数序列,一个区间[L,R]的价值定义为:三个序列中,这个区间的极差(最大值与最小值之差)的乘积. 求所有区间的价值之和.答案对\(2^ ...
- [JXOI2017]颜色 线段树扫描线 + 单调栈
---题面--- 题解: 首先题目要求删除一些颜色,换个说法就是要求保留一些颜色,那么观察到,如果我们设ll[i]和rr[i]分别表示颜色i出现的最左边的那个点和最右边的那个点,那么题目就是在要求我们 ...
- Educational Codeforces Round 61 (Rated for Div. 2) G(线段树,单调栈)
#include<bits/stdc++.h>using namespace std;int st[1000007];int top;int s[1000007],t[1000007];i ...
- [BZOJ 2957]楼房重建(THU2013集训)(线段树维护单调栈)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2957 分析: 根据题意,就是比较斜率大小 只看一段区间的话,那么这段区间能看见的楼房数量就是这 ...
- ACM学习历程—HDU 5289 Assignment(线段树 || RMQ || 单调队列)
Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered fro ...
- 洛谷 P4198 楼房重建 线段树维护单调栈
P4198 楼房重建 题目链接 https://www.luogu.org/problemnew/show/P4198 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上 ...
- [CSP-S模拟测试]:God Knows(线段树维护单调栈)
题目描述 小$w$来到天堂的门口,对着天堂的大门发呆.大门上有一个二分图,左边第$i$个点连到右边第$p_i$个点.(保证$p_i$是一个排列).小$w$每次可以找左边某个对应连线尚未被移除的点$i$ ...
- 1304F2 - Animal Observation (hard version) 线段树or单调队列 +DP
1304F2 - Animal Observation (hard version) 线段树or单调队列 +DP 题意 用摄像机观察动物,有两个摄像机,一个可以放在奇数天,一个可以放在偶数天.摄像机在 ...
随机推荐
- FFmpeg 入门(1):截取视频帧
本文转自:FFmpeg 入门(1):截取视频帧 | www.samirchen.com 背景 在 Mac OS 上如果要运行教程中的相关代码需要先安装 FFmpeg,建议使用 brew 来安装: // ...
- Python爬虫学习笔记之爬虫基础库
知识预览 beautifulsoup的简单使用 beautifulsoup的遍历文档树 beautifulsoup的搜索文档树 beautifulsoup的css选择器 回到顶部 beautifuls ...
- Nginx 日志
原文地址:Nginx深入详解之日志 作者:scq2099yt 一.日志分类 Nginx日志主要分为两种:访问日志和错误日志.日志开关在Nginx配置文件(/etc/nginx/nginx ...
- C++求矩阵的鞍点
矩阵的鞍点就是指它在本行中的值最大,在本列中的值最小. 求解思路: 求出每行的最大值MaxRow以及每列的最小值MinColumn 保存行最大值的位置和列最小值的位置 如果行最大值得位置和列最小值的相 ...
- 再也不学AJAX了!(二)使用AJAX
在上一篇文章中我们知道,AJAX是一系列技术的统称.在本篇中我们将更进一步,详细解释如何使用Ajax技术在项目中获取数据.而为了解释清楚,我们首先要搞清楚我们是从哪里获取数据的,其次我们关注的才是获取 ...
- Hive中排序和聚集
//五种子句是有严格顺序的: where → group by → having → order by → limit ; //distinct关键字返回唯一不同的值(返回age和id均不相同的记录) ...
- openwrt下如何只编译uboot
答:如使用以下命令编译nxp的layerscape系列芯片相关的uboot: make package/boot/uboot-layerscape/prepare make package/boot/ ...
- [CF911F]Tree Destruction
题意翻译 给你一棵树,每次挑选这棵树的两个叶子,加上他们之间的边数(距离),然后将其中一个点去掉,问你边数(距离)之和最大可以是多少. 首先我们知道,到一个点距离最远的点是直径的端点.考虑贪心,如果我 ...
- CSS样式 vertical-align:middle 垂直居中生效情况
vertical-align:middle 是依赖div内子元素最高的行高来实现对某元素居中的 -------不存在浮动时可以直接生效垂直居中 HTML .box1{ display: table- ...
- 分布式文档存储数据库(MongoDB)副本集配置
副本集特征: N 个节点的集群 任何节点可作为主节点 所有写入操作都在主节点上 自动故障转移 自动恢复 相关文章: http://www.cnblogs.com/huangxincheng/archi ...