zoukankan      html  css  js  c++  java
  • BZOJ4373 算术天才⑨与等差数列 【线段树】*

    BZOJ4373 算术天才⑨与等差数列


    Description

    算术天才⑨非常喜欢和等差数列玩耍。
    有一天,他给了你一个长度为n的序列,其中第i个数为a[i]。
    他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序后能否形成公差为k的等差数列。
    当然,他还会不断修改其中的某一项。
    为了不被他鄙视,你必须要快速并正确地回答完所有问题。
    注意:只有一个数的数列也是等差数列。

    Input

    第一行包含两个正整数n,m(1<=n,m<=300000),分别表示序列的长度和操作的次数。
    第二行包含n个整数,依次表示序列中的每个数ai
    接下来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的个数来进行解密。

    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


    满足等差数列的条件:
    1.gcd(ai−ai+1)%k=0(li<r)
    2.max(ai)−min(ai)=(r−l)∗k(l≤i≤r)
    3.区间内没有重复的数3.区间内没有重复的数3.


    对于第一个,我们可以用线段树维护相邻两点值的差的gcd
    对于第二个,直接维护最大最小值
    对于第三个,我们记录区间内所有数上一次出现的位置,取max,如果这个位置大于l就重复了

    然后对于上一次出现的数,可以直接暴力开set,大概只需要n∗2个set就够用了

    然后别挥霍内存就可以了


    还有一个需要注意
    就是k=0的情况要特判掉


      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 300001
      4 #define LD (t<<1)
      5 #define RD (t<<1|1)
      6 int t1;
      7 map<int,int> mp;
      8 set<int> s[N<<1];
      9 int n,m,val[N],pre[N];
     10 struct Node{int gcd,minv,maxv,pre;}T[N<<2],tmp1,tmp2,res;
     11 int t2;
     12 int read(){
     13   int ans=0,w=1;char c=getchar();
     14   while(!isdigit(c)&&c!='-')c=getchar();
     15   if(c=='-')w=-1,c=getchar();
     16   while(isdigit(c))ans=(ans<<1)+(ans<<3)+c-'0',c=getchar();
     17   return ans*w;
     18 }
     19 int gcd(int a,int b){return b?gcd(b,a%b):a;}
     20 Node merge(Node l,Node r){
     21   res.gcd=gcd(l.gcd,r.gcd);
     22   res.maxv=max(l.maxv,r.maxv);
     23   res.minv=min(l.minv,r.minv);
     24   res.pre=max(l.pre,r.pre);
     25   return res;
     26 }
     27 void build(int t,int l,int r){
     28   if(l>r)return;
     29   if(l==r){
     30     T[t].gcd=abs(val[l]-val[l+1]);
     31     T[t].minv=T[t].maxv=val[l];
     32     T[t].pre=pre[l];
     33     return;
     34   }
     35   int mid=(l+r)>>1;
     36   build(LD,l,mid);
     37   build(RD,mid+1,r);
     38   T[t]=merge(T[LD],T[RD]);
     39 }
     40 void modify(int t,int l,int r,int pos){
     41   if(l==r){
     42     T[t].gcd=abs(val[l]-val[l+1]);
     43     T[t].minv=T[t].maxv=val[l];
     44     T[t].pre=pre[l];
     45     return;
     46   }
     47   int mid=(l+r)>>1;
     48   if(pos<=mid)modify(LD,l,mid,pos);
     49   else modify(RD,mid+1,r,pos);
     50   T[t]=merge(T[LD],T[RD]);
     51 }
     52 Node query(int t,int l,int r,int L,int R){
     53   if(L<=l&&r<=R)return T[t];
     54   int mid=(l+r)>>1;
     55   if(R<=mid)return query(LD,l,mid,L,R);
     56   if(L>mid)return query(RD,mid+1,r,L,R);
     57   return merge(query(LD,l,mid,L,mid),query(RD,mid+1,r,mid+1,R));
     58 }
     59 int main(){
     60   freopen("4373.in","r",stdin);
     61   freopen("4373.out","w",stdout);
     62   scanf("%d%d",&n,&m);
     63   int cnt=0;
     64   for(int i=1;i<=n;i++){
     65     val[i]=read();
     66     if(!mp[val[i]]){
     67       mp[val[i]]=++cnt;
     68       s[cnt].insert(0);
     69       s[cnt].insert(n+1);
     70       s[cnt].insert(i);
     71       pre[i]=0;
     72     }else{
     73       s[mp[val[i]]].insert(i);
     74       pre[i]=*--(s[mp[val[i]]].lower_bound(i)); 
     75     }
     76   }
     77   val[n+1]=val[n];
     78   build(1,1,n);
     79   int las=0;
     80   while(m--){
     81     int op=read();
     82     if(op==1){
     83       int x=read()^las,y=read()^las;
     84       int t=mp[val[x]];
     85       int tmp=*s[t].upper_bound(x);
     86       if(tmp!=n+1){
     87         pre[tmp]=pre[x];
     88         modify(1,1,n,tmp);
     89       }
     90       s[t].erase(x);
     91       if(!mp[y]){
     92         mp[y]=++cnt;
     93         s[cnt].insert(0);
     94         s[cnt].insert(n+1);
     95         s[cnt].insert(x);
     96         pre[x]=0;
     97       }else{
     98         s[mp[y]].insert(x);
     99         pre[x]=*--s[t].lower_bound(x);
    100       }
    101       t=mp[y];
    102       tmp=*s[t].upper_bound(x);
    103       if(tmp!=n+1){
    104         pre[tmp]=x;
    105         modify(1,1,n,x);
    106       }
    107       if(x==n)val[n+1]=y;
    108       val[x]=y;
    109       modify(1,1,n,x);
    110       if(x>1)modify(1,1,n,x-1);
    111     }else{
    112       int l=read()^las,r=read()^las,k=read()^las;
    113       if(l==r){printf("Yes
    ");++las;continue;}
    114       tmp1=query(1,1,n,l,r-1);
    115       tmp2=merge(tmp1,query(1,1,n,r,r));
    116       if(!k){
    117         if(tmp2.minv==tmp2.maxv)++las,printf("Yes
    ");
    118         else printf("No
    ");
    119         continue;
    120       }
    121       if(tmp1.gcd%k){printf("No
    ");;continue;}
    122       if(tmp2.pre>=l){printf("No
    ");continue;}
    123       if(tmp2.maxv-tmp2.minv!=(r-l)*k){printf("No
    ");continue;}
    124       las++;
    125       printf("Yes
    ");
    126     }
    127   }
    128   printf("
    ");
    129   return 0;
    130 }
  • 相关阅读:
    自定义样式滚动条
    html文本超出加省略号
    getcomputedstyle和style的区别
    模块化设计
    js数组取出非重复元素
    vue 获取元素高度
    js 滚动条滑动
    swiper基本使用
    flex弹性盒子布局
    js 地区三级联动 2
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676254.html
Copyright © 2011-2022 走看看