【线段树】BZOJ4373算术天才与等差数列
2016-03-02 00:00
309 查看
传送门
Description
给定一个长度为 n 的序列,其中第 i 个数为 ai。
有 m 次操作,每次要么修改其中的某一项,要么给出询问l; r; k,问区间 [l; r] 内的数从小到大排序后能否形成公差为 k 的等差数列。
Input
第一行包含两个正整数n,m(1<=n,m<=300000),分别表示序列的长度和操作的次数。
第二行包含n个整数,依次表示序列中的每个数ai(0<=ai<=109)。
接下来m行,每行一开始为一个数op,
若op=1,则接下来两个整数x,y(1<=x<=n,0<=y<=109),表示把ax修改为y。
若op=2,则接下来三个整数l,r,k(1<=l<=r<=n,0<=k<=109),表示一个询问。
在本题中,x,y,l,r,k都是经过加密的,都需要异或你之前输出的Yes的个数来进行解密。
Output
输出若干行,对于每个询问,如果可以形成等差数列,那么输出Yes,否则输出No。
Sample Input
5 3
1 3 2 5 6
2 1 5 1
1 5 4
2 1 5 1
Sample Output
No
Yes
条件一:这一区间的最大值与最小值的差满足等差数列的公式(ai−aj=d∗(i−j))。
条件二:这一区间的所有数模k的值相同。
条件二相对于条件一麻烦得多,于是考虑相邻的两个数的差。如果差x模k的值为0,则满足。
这样就可以用线段树水过辣。
简单滴解释一下下面线段树中的标记含义。
maxv:区间最大值。minv:区间最小值。
l:左端点的值。r:右端点的值。
k:区间关于k成等差数列。
可能在写的过程中up函数比较难写。
注意gcd(a,b)中不能模0。
据说可以用等差数列的和、各项平方的和水过 2333
Description
给定一个长度为 n 的序列,其中第 i 个数为 ai。
有 m 次操作,每次要么修改其中的某一项,要么给出询问l; r; k,问区间 [l; r] 内的数从小到大排序后能否形成公差为 k 的等差数列。
Input
第一行包含两个正整数n,m(1<=n,m<=300000),分别表示序列的长度和操作的次数。
第二行包含n个整数,依次表示序列中的每个数ai(0<=ai<=109)。
接下来m行,每行一开始为一个数op,
若op=1,则接下来两个整数x,y(1<=x<=n,0<=y<=109),表示把ax修改为y。
若op=2,则接下来三个整数l,r,k(1<=l<=r<=n,0<=k<=109),表示一个询问。
在本题中,x,y,l,r,k都是经过加密的,都需要异或你之前输出的Yes的个数来进行解密。
Output
输出若干行,对于每个询问,如果可以形成等差数列,那么输出Yes,否则输出No。
Sample Input
5 3
1 3 2 5 6
2 1 5 1
1 5 4
2 1 5 1
Sample Output
No
Yes
条件一:这一区间的最大值与最小值的差满足等差数列的公式(ai−aj=d∗(i−j))。
条件二:这一区间的所有数模k的值相同。
条件二相对于条件一麻烦得多,于是考虑相邻的两个数的差。如果差x模k的值为0,则满足。
这样就可以用线段树水过辣。
简单滴解释一下下面线段树中的标记含义。
maxv:区间最大值。minv:区间最小值。
l:左端点的值。r:右端点的值。
k:区间关于k成等差数列。
可能在写的过程中up函数比较难写。
注意gcd(a,b)中不能模0。
据说可以用等差数列的和、各项平方的和水过 2333
#include <iostream> #include <cstdio> #include <algorithm> #define MAXN 300005 using namespace std; int n, m, num[MAXN]; inline int id(int x,int y){return (x+y)|(x!=y);} int gcd(int a,int b) { if(!a)return b; if(!b)return a; return gcd(b,a%b); } struct node { int maxv, minv, l, r, k; }; struct SGE { node t[MAXN<<1]; inline void up(node &a,node &b,node &c) { a.maxv=max(b.maxv,c.maxv), a.minv=min(b.minv,c.minv); a.l=b.l, a.r=c.r; a.k=gcd(gcd(b.k,c.k),abs(c.l-b.r)); } void build(int code,int l,int r) { if(l==r) { t[code].maxv=t[code].minv=t[code].l=t[code].r=num[l]; return; } int mid=(l+r)>>1; int lc=id(l,mid), rc=id(mid+1,r); build(lc,l,mid), build(rc,mid+1,r); up(t[code],t[lc],t[rc]); } node query(int code,int l,int r,int ql,int qr) { if(l==ql&&r==qr)return t[code]; int mid=(l+r)>>1; if(qr<=mid)return query(id(l,mid),l,mid,ql,qr); if(mid<ql)return query(id(mid+1,qr),mid+1,r,ql,qr); int lc=id(l,mid), rc=id(mid+1,r); node ans, ans1, ans2; ans1=query(lc,l,mid,ql,mid), ans2=query(rc,mid+1,r,mid+1,qr); up(ans,ans1,ans2); return ans; } void change(int code,int l,int r,int pos,int d) { if(l==r) { t[code].maxv=t[code].minv=t[code].l=t[code].r=d; return; } int mid=(l+r)>>1; int lc=id(l,mid), rc=id(mid+1,r); if(pos<=mid)change(lc,l,mid,pos,d); else change(rc,mid+1,r,pos,d); up(t[code],t[lc],t[rc]); } }sge; bool solve(int l,int r,int k) { if(l==r)return 1; node ans=sge.query(id(1,n),1,n,l,r); if(ans.k==k&&ans.maxv-ans.minv==k*(r-l))return 1; return 0; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;++i)scanf("%d",&num[i]); sge.build(id(1,n),1,n); int key=0, f, l, r, x; while(m--) { scanf("%d%d%d",&f,&l,&r); l^=key, r^=key; if(f==1) sge.change(id(1,n),1,n,l,r); else { scanf("%d",&x); x^=key; if(solve(l,r,x)) { ++key; puts("Yes"); } else puts("No"); } } return 0; }
相关文章推荐
- 线段树题集
- 线段树
- hdu1754
- HDU1394
- 敌兵布阵 (1)
- I Hate It (1)
- LCIS (2)
- A Simple Problem with Integers (2)
- Mayor's posters (3)
- Buy Tickets (3)
- 线段树
- UVA - 12532 Interval Product
- POJ 3264 Balanced Lineup
- hdu 1542 求矩形并的面积
- 关于数据结构之线段树
- poj 3225 关于集合运算
- poj 2352
- hihocoder #1069 线段树
- hdu1166敌兵布阵(线段树点修改)
- 【51nod 6级题目】XOR key 问题