zoukankan      html  css  js  c++  java
  • [BZOJ4373]算术天才⑨与等差数列(线段树)

    [l,r]中所有数排序后能构成公差为k的等差数列,当且仅当

    1.区间中最大数-最小数=k*(r-l)

    2.k能整除区间中任意两个相邻数之差,即k | gcd(a[l+1]-a[l],a[l+2]-a[l+1],...,a[r]-a[r-1])

    3.区间中任意两个数不相同,即设pre[i]为序列中i之前第一个与a[i]相等的数的位置,则max(pre[l],...,pre[r])<l

    于是线段树分别维护:区间最大值,区间最小值,区间相邻差的gcd,区间pre的最大值即可。

    注意特判下l=r和k=0的情况。

      1 #include<set>
      2 #include<map>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<algorithm>
      6 #define ls (x<<1)
      7 #define rs (ls|1)
      8 #define lson ls,L,mid
      9 #define rson rs,mid+1,R
     10 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     11 using namespace std;
     12 
     13 const int N=300010;
     14 int n,m,tot,op,x,y,l,r,k,w,a[N],d[N],pre[N],Gcd[N<<2],mn[N<<2],mx[N<<2],mxp[N<<2];
     15 set<int>S[N<<1];
     16 map<int,int>mp;
     17 
     18 int gcd(int a,int b){ return b ? gcd(b,a%b) : a; }
     19 
     20 void upd(int x){
     21     mn[x]=min(mn[ls],mn[rs]); mx[x]=max(mx[ls],mx[rs]);
     22     Gcd[x]=gcd(Gcd[ls],Gcd[rs]); mxp[x]=max(mxp[ls],mxp[rs]);
     23 }
     24 
     25 void build(int x,int L,int R){
     26     if (L==R){ Gcd[x]=d[L]; mn[x]=mx[x]=a[L]; mxp[x]=pre[L]; return; }
     27     int mid=(L+R)>>1;
     28     build(lson); build(rson); upd(x);
     29 }
     30 
     31 void mdf(int x,int L,int R,int pos,int k,int op){
     32     if (L==R){
     33         if (op==0) Gcd[x]=k;
     34         if (op==1) mn[x]=mx[x]=k;
     35         if (op==2) mxp[x]=k;
     36         return;
     37     }
     38     int mid=(L+R)>>1;
     39     if (pos<=mid) mdf(lson,pos,k,op); else mdf(rson,pos,k,op);
     40     upd(x);
     41 }
     42 
     43 int que(int x,int L,int R,int l,int r,int op){
     44     if (L==l && r==R){
     45         if (op==0) return Gcd[x];
     46         if (op==1) return mn[x];
     47         if (op==2) return mx[x];
     48         if (op==3) return mxp[x];
     49     }
     50     int mid=(L+R)>>1;
     51     if (r<=mid) return que(lson,l,r,op);
     52     else if (l>mid) return que(rson,l,r,op);
     53         else{
     54             if (op==0) return gcd(que(lson,l,mid,op),que(rson,mid+1,r,op));
     55             if (op==1) return min(que(lson,l,mid,op),que(rson,mid+1,r,op));
     56             if (op==2) return max(que(lson,l,mid,op),que(rson,mid+1,r,op));
     57             if (op==3) return max(que(lson,l,mid,op),que(rson,mid+1,r,op));
     58         }
     59     return 0;
     60 }
     61 
     62 int main(){
     63     freopen("bzoj4373.in","r",stdin);
     64     freopen("bzoj4373.out","w",stdout);
     65     scanf("%d%d",&n,&m);
     66     rep(i,1,n){
     67         scanf("%d",&a[i]),d[i]=abs(a[i]-a[i-1]);
     68         if (!mp.count(a[i])){
     69             mp[a[i]]=++tot; pre[i]=0; S[tot].insert(i);
     70         }else{
     71             int t=mp[a[i]]; pre[i]=*(--S[t].end()); S[t].insert(i);
     72         }
     73     }
     74     build(1,1,n);
     75     rep(i,1,m){
     76         scanf("%d",&op);
     77         if (op==1){
     78             scanf("%d%d",&x,&y); x^=w; y^=w;
     79             if (y==a[x]) continue;
     80             d[x]=abs(y-a[x-1]); mdf(1,1,n,x,d[x],0);
     81             if (x<n) d[x+1]=abs(a[x+1]-y),mdf(1,1,n,x+1,d[x+1],0);
     82             int t=mp[a[x]]; set<int>::iterator it=S[t].upper_bound(x);
     83             if (it!=S[t].end()) pre[*it]=pre[x],mdf(1,1,n,*it,pre[*it],2); S[t].erase(x);
     84             a[x]=y; mdf(1,1,n,x,a[x],1);
     85             if (!mp.count(a[x])){
     86                 mp[a[x]]=++tot; pre[x]=0; S[tot].insert(x); mdf(1,1,n,x,pre[x],2);
     87             }else{
     88                 int t=mp[a[x]];
     89                 set<int>::iterator it=S[t].insert(x).first;
     90                 if (it==S[t].begin()) pre[x]=0; else pre[x]=*(--it);
     91                 mdf(1,1,n,x,pre[x],2);
     92                 it=S[t].upper_bound(x);
     93                 if (it!=S[t].end()) pre[*it]=x,mdf(1,1,n,*it,pre[*it],2);
     94             }
     95         }else{
     96             scanf("%d%d%d",&l,&r,&k); l^=w; r^=w; k^=w;
     97             if (l==r){ w++; puts("Yes"); continue; }
     98             if (!k){
     99                 if (que(1,1,n,l,r,2)==que(1,1,n,l,r,1)) w++,puts("Yes"); else puts("No");
    100                 continue;
    101             }
    102             if (que(1,1,n,l,r,2)-que(1,1,n,l,r,1)!=1ll*k*(r-l) || que(1,1,n,l+1,r,0)%k || que(1,1,n,l,r,3)>=l) puts("No");
    103                 else w++,puts("Yes");
    104         }
    105     }
    106     return 0;
    107 }
  • 相关阅读:
    Ionic Cordova 环境配置window
    滚动条超出表格标题,表格标题固定
    逗号分隔查询
    sulin LuceneNet 搜索二
    LuceneNet 搜索一
    Sql 竖表转横表
    div 无缝滚动
    【bfs】【中等难度】wikioi3055 青铜莲花池
    【bfs】【中等难度】tyvj P1234
    【简单思考】noip模拟赛 NTR酋长
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9909295.html
Copyright © 2011-2022 走看看