中国(北方)大学生程序设计训练赛(第一周)-F(线段树)
2017-03-06 18:55
375 查看
题目链接:F
首先知道等差数列的一个性质: abs(ai−aj)=k∗d ,所以一个区间的任意两个相邻项之差的绝对值的gcd 应该是公差 d ,然后通过最大值-最小值也可以确定一个公差,这两个公差相等的话,且区间内无相同元素,则表明是等差数列。特别的,当最大值==最小值也是等差数列。
查询区间内是否有相同元素可以用线段树查询,pre[i] 表示 a[i] 第一次出现的位置,若区间的 max(pre[i])<l ,则无重复元素。
首先知道等差数列的一个性质: abs(ai−aj)=k∗d ,所以一个区间的任意两个相邻项之差的绝对值的gcd 应该是公差 d ,然后通过最大值-最小值也可以确定一个公差,这两个公差相等的话,且区间内无相同元素,则表明是等差数列。特别的,当最大值==最小值也是等差数列。
查询区间内是否有相同元素可以用线段树查询,pre[i] 表示 a[i] 第一次出现的位置,若区间的 max(pre[i])<l ,则无重复元素。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int INF=1e9+7; const int maxn=1e5+7; int ma[maxn<<2],mi[maxn<<2],gd[maxn<<2],pre[maxn<<2],vis[1000007]; void init() { memset(ma,0,sizeof(ma)); memset(mi,0,sizeof(mi)); memset(gd,0,sizeof(gd)); memset(pre,0,sizeof(pre)); memset(vis,0,sizeof(vis)); } int gcd(int a,int b) { if(b==0) return a; return a%b?gcd(b,a%b):b; } int p; void push_up(int rt) { ma[rt]=max(ma[rt<<1],ma[rt<<1|1]); mi[rt]=min(mi[rt<<1],mi[rt<<1|1]); gd[rt]=gcd(gd[rt<<1],gd[rt<<1|1]); pre[rt]=max(pre[rt<<1],pre[rt<<1|1]); } void build(int rt,int l,int r) { if(l==r) { scanf("%d",&ma[rt]); mi[rt]=ma[rt]; pre[rt]=vis[ma[rt]]; if(l!=1) gd[rt]=abs(ma[rt]-p); p=ma[rt]; vis[ma[rt]]=l; return ; } if(l==r) return ; int mid=(l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); push_up(rt); } int query_max(int rt,int l,int r,int ql,int qr) { if(l>=ql&&r<=qr) return ma[rt]; int res=-INF; int mid=(l+r)>>1; if(ql<=mid) res=max(res,query_max(rt<<1,l,mid,ql,qr)); if(qr>mid) res=max(res,query_max(rt<<1|1,mid+1,r,ql,qr)); return res; } int query_min(int rt,int l,int r,int ql,int qr) { if(l>=ql&&r<=qr) return mi[rt]; int res=INF; int mid=(l+r)>>1; if(ql<=mid) res=min(res,query_min(rt<<1,l,mid,ql,qr)); if(qr>mid) res=min(res,query_min(rt<<1|1,mid+1,r,ql,qr)); return res; } int query_pre(int rt,int l,int r,int ql,int qr) { if(l>=ql&&r<=qr) return pre[rt]; int res=-INF; int mid=(l+r)>>1; if(ql<=mid) res=max(res,query_pre(rt<<1,l,mid,ql,qr)); if(qr>mid) res=max(res,query_pre(rt<<1|1,mid+1,r,ql,qr)); return res; } int query_gcd(int rt,int l,int r,int ql,int qr) { if(l>=ql&&r<=qr) return gd[rt]; int mid=(l+r)>>1; if(qr<=mid) return query_gcd(rt<<1,l,mid,ql,qr); if(ql>mid) return query_gcd(rt<<1|1,mid+1,r,ql,qr); return gcd(query_gcd(rt<<1,l,mid,ql,qr),query_gcd(rt<<1|1,mid+1,r,ql,qr)); } int main() { int n,q; while(~scanf("%d%d",&n,&q)) { init(); int l,r; build(1,1,n); while(q--) { scanf("%d%d",&l,&r); int low=query_min(1,1,n,l,r); int high=query_max(1,1,n,l,r); if(low==high||l==r) puts("Yes"); else if(query_pre(1,1,n,l,r)<l&&1LL*query_gcd(1,1,n,l+1,r)*(r-l)==1LL*(high-low)) puts("Yes"); else puts("No"); } } return 0; }
相关文章推荐
- 中国(北方)大学生程序设计训练赛(第一周)(Problem F: 等差区间-线段树+等差数列平方和公式)
- 中国(北方)大学生程序设计训练赛(第一周)(Problem D: 数学题-二分+双指针)
- 中国(北方)大学生程序设计训练赛(第一周)-A(生成树计数)
- 中国(北方)大学生程序设计训练赛(第一周)(Problem E: Water Problem-矩阵快速幂)
- 等差区间(写的很脑残)——中国(北方)大学生程序设计训练赛(第一周)F
- 中国(北方)大学生程序设计训练赛(第一周)
- 中国(北方)大学生程序设计训练赛(第一周)(Problem B: 埃蒙的时空航道-最小割转dp+贪心)
- 中国(北方)大学生程序设计训练赛(第一周)E. water problem
- 中国(北方)大学生程序设计训练赛(第一周) (D E)
- 中国(北方)大学生程序设计训练赛(第一周)E. water problem
- 中国(北方)大学生程序设计训练赛(第一周)-D (二分)
- 矩阵快速幂-中国(北方)大学生程序设计训练赛(第一周)Water Problem
- 中国(北方)大学生程序设计训练赛(第二周)(Problem C: A Water Problem-dp)
- 中国(北方)大学生程序设计训练赛(第二周) (A B D G)
- 中国(北方)大学生程序设计训练赛(第二周)(Problem G: Connected Components-并查集)
- 中国(北方)大学生程序设计训练赛(第三周)(Interesting sequence-找规律)
- 中国(北方)大学生程序设计训练赛(第三周)(List likes playing card-期望)
- 中国(北方)大学生程序设计训练赛(第二周)(Problem A: Common Substrings-hash)
- 中国(北方)大学生程序设计训练赛(第二周)(Problem B: A Boring Game-乱搞)
- 赛码"BestCoder"杯中国大学生程序设计冠军赛1001——Movie