[bzoj4373]算术天才⑨与等差数列
来自FallDream的博客,未经允许,请勿转载,谢谢。
算术天才⑨非常喜欢和等差数列玩耍。
有一天,他给了你一个长度为n的序列,其中第i个数为a[i]。
他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序后能否形成公差为k的等差数列。
当然,他还会不断修改其中的某一项。
为了不被他鄙视,你必须要快速并正确地回答完所有问题。
注意:只有一个数的数列也是等差数列。
第一行包含两个正整数n,m(1<=n,m<=300000),分别表示序列的长度和操作的次数。
第二行包含n个整数,依次表示序列中的每个数a[i](0<=a[i]<=10^9)。
接下来m行,每行一开始为一个数op,
若op=1,则接下来两个整数x,y(1<=x<=n,0<=y<=10^9),表示把a[x]修改为y。
若op=2,则接下来三个整数l,r,k(1<=l<=r<=n,0<=k<=10^9),表示一个询问。
在本题中,x,y,l,r,k都是经过加密的,都需要异或你之前输出的Yes的个数来进行解密。
只想到一个比较麻烦的判断方式
一个序列合法,当且仅当最小/最大值/权值和合法,没有相同元素且差分的gcd是k。
除了没有相同元素这个条件,其他的都能线段树求。
考虑每种权值维护一棵平衡树,然后线段树维护区间 每一个位置和她相同的上一个格子的位置 的最大值,如果这个最大值小于l,那么就没有相同元素。
常数巨大。
除了gcd以外其他都是严格nlogn的 区间gcd复杂度我不知道是什么 感觉是nlogn但是不会证。。
另:300题打卡。
#include<iostream> #include<cstdio> #include<map> #include<set> #define ll long long #define MN 300000 #define N 524288 #define It set<int>::iterator using namespace std; inline long long read() { long long x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } struct data{int mx,mn;ll sum; friend data operator +(data a,data b){return(data){max(a.mx,b.mx),min(a.mn,b.mn),a.sum+b.sum};} }; struct Tree{int l,r;data x;}T[MN*4+5]; int t[N*2+5],t2[N*2+5],cnt=0,a[MN+5],last=0,n,m; set<int> st[MN*2+5]; map<int,int> mp; inline int gcd(int x,int y){return !y?x:gcd(y,x%y);} inline int abs(int x){return x<0?-x:x;} int Query2(int l,int r) { int res=0; for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1) { if(~l&1) res=gcd(res,t2[l+1]); if( r&1) res=gcd(res,t2[r-1]); } return res; } void Modify2(int x,int ad) { t2[x+=N]=ad; for(x>>=1;x;x>>=1) t2[x]=gcd(t2[x<<1],t2[x<<1|1]); } int Query(int l,int r) { int res=0; for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1) { if(~l&1) res=max(res,t[l+1]); if( r&1) res=max(res,t[r-1]); } return res; } void Modify(int x,int ad) { t[x+=N]=ad; for(x>>=1;x;x>>=1) t[x]=max(t[x<<1],t[x<<1|1]); } void Build(int x,int l,int r) { if((T[x].l=l)==(T[x].r=r)) {T[x].x=(data){a[l],a[l],a[l]};return;} int mid=l+r>>1; Build(x<<1,l,mid);Build(x<<1|1,mid+1,r); T[x].x=T[x<<1].x+T[x<<1|1].x; } void Modify(int x,int k,int v) { if(T[x].l==T[x].r) T[x].x=(data){v,v,v}; else { int mid=T[x].l+T[x].r>>1; if(k<=mid) Modify(x<<1,k,v); else Modify(x<<1|1,k,v); T[x].x=T[x<<1].x+T[x<<1|1].x; } } data Query(int x,int l,int r) { if(T[x].l==l&&T[x].r==r) return T[x].x; int mid=T[x].l+T[x].r>>1; if(r<=mid) return Query(x<<1,l,r); else if(l>mid) return Query(x<<1|1,l,r); else return Query(x<<1,l,mid)+Query(x<<1|1,mid+1,r); } int main() { n=read();m=read(); for(int i=1;i<=n;++i) { !mp[a[i]=read()]?mp[a[i]]=++cnt:0; int x=mp[a[i]]; if(st[x].begin()!=st[x].end()) Modify(i,*(--st[x].end())); st[x].insert(i); if(i>1) Modify2(i-1,abs(a[i]-a[i-1])); } Build(1,1,n); for(int i=1;i<=m;++i) { int op=read(); if(op==1) { int x=read()^last,y=read()^last; if(a[x]==y) continue; if(x!=n) Modify2(x,abs(a[x+1]-y)); if(x!=1) Modify2(x-1,abs(y-a[x-1])); int ha=mp[a[x]]; It it=st[ha].lower_bound(x),it2=it; if(++it!=st[ha].end()) Modify(*it,(it2==st[ha].begin()?0:*(--it2))); st[ha].erase(--it); !mp[y]?mp[y]=++cnt:0;ha=mp[y]; it=st[ha].lower_bound(x),it2=it; if(it!=st[ha].end()) Modify(*it,x); if(it2!=st[ha].end()&&it2!=st[ha].begin()) Modify(x,*(--it2)); else Modify(x,0); a[x]=y;Modify(1,x,y);st[ha].insert(x); } else { int l=read()^last,r=read()^last,k=read()^last; data x=Query(1,l,r);bool flag=0; if(l==r) {puts("Yes"),++last;continue;} if(!k) { if(x.mn==x.mx) puts("Yes"),++last; else puts("No"); continue; } if(x.sum!=1LL*x.mn*(r-l+1)+1LL*(r-l+1)*(r-l)/2*k) flag=1; else if(x.mx!=x.mn+1LL*(r-l)*k) flag=1; else { int Gcd=Query2(l,r-1),MxLast=Query(l,r); if(Gcd!=k||MxLast>=l) flag=1; } if(flag) puts("No"); else puts("Yes"),++last; } } return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream