zoukankan      html  css  js  c++  java
  • BZOJ4373: 算术天才⑨与等差数列

    n<=3e5的数列,m<=3e5个操作:把第x个数修改成y,或询问从x到y这个区间能否构成公差z的等差数列。

    二逼做法:考虑一个序列在什么情况下才能构成公差z的等差数列。

    首先,最大值和最小值的差是z*(y-x)。

    其次,相邻两数的差的gcd是z。

    再者,没有重复的数字。

    前两个比较好搞,线段树,第三个其实就是每个数Ai记一个pre[i]表示Ai之前和Ai相同的第一个数字的下标,然后区间x到y的pre的最大值<x即可。

    那这个怎么修改呢,每次修改涉及到三个数字:Ai后面的某个pre[j]=i的j,修改后Ai后面某个pre[j]=i的j,Ai自己的pre。现在就是要找一定权值的大于某个数字的第一个数字,这里的数字即下标。所以每个权值开一个平衡树set存这个权值的所有下标,每次修改只需要lowerbound找一下Ai的下标i对应的迭代器,然后他的下一个和上一个也就很清楚了,分类看是不是最后一个和第一个来修改。

    还有一个问题,权值被强制在线了,要写个动态离散化,二逼离散化:map,文艺离散化:hash。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<cstdlib>
      5 #include<set>
      6 //#include<time.h>
      7 #include<math.h>
      8 //#include<assert.h>
      9 //#include<queue>
     10 #include<iostream>
     11 using namespace std;
     12  
     13 int n,m;
     14 #define maxn 600011
     15 #define It set<int>::iterator
     16 int num[maxn],pre[maxn];
     17 set<int> s[maxn<<1];
     18 struct Doo
     19 {
     20     int id,x,y,z;
     21 }doo[maxn];
     22 int gcd(int a,int b) {return b?gcd(b,a%b):a;}
     23 struct SMT
     24 {
     25     struct Node
     26     {
     27         int Max,Min,gcd;
     28         int l,r;
     29         int ls,rs;
     30     }a[maxn<<1];
     31     int size;
     32     SMT() {size=0;}
     33     void up(int x)
     34     {
     35         const int &p=a[x].ls,&q=a[x].rs;
     36         a[x].Max=max(a[p].Max,a[q].Max);
     37         a[x].Min=min(a[p].Min,a[q].Min);
     38         a[x].gcd=gcd(gcd(a[p].gcd,a[q].gcd),fabs(num[a[q].l]-num[a[p].r]));
     39     }
     40     void build(int &x,int L,int R)
     41     {
     42         x=++size;
     43         a[x].l=L;a[x].r=R;
     44         if (a[x].l==a[x].r)
     45         {
     46             a[x].ls=a[x].rs=0;
     47             a[x].Max=num[L];
     48             a[x].Min=num[L];
     49             a[x].gcd=0;
     50             return;
     51         }
     52         const int mid=(L+R)>>1;
     53         build(a[x].ls,L,mid);
     54         build(a[x].rs,mid+1,R);
     55         up(x);
     56     }
     57     void build() {int x;build(x,1,n);}
     58     int ql,qr,v;
     59     void modify(int x)
     60     {
     61         if (a[x].l==a[x].r) a[x].Max=a[x].Min=v;
     62         else
     63         {
     64             const int mid=(a[x].l+a[x].r)>>1;
     65             if (ql<=mid) modify(a[x].ls);
     66             else modify(a[x].rs);
     67             up(x);
     68         }
     69     }
     70     void modify(int x,int v)
     71     {
     72         ql=x;this->v=v;
     73         modify(1);
     74     }
     75     int query(int x)
     76     {
     77         if (ql<=a[x].l && a[x].r<=qr)
     78         {
     79             if (v==1) return a[x].Max;
     80             if (v==2) return a[x].Min;
     81             if (v==3) return a[x].gcd;
     82         }
     83         const int mid=(a[x].l+a[x].r)>>1;
     84         int ans;bool flag;
     85         if (v==1) ans=-1;
     86         if (v==2) ans=0x3f3f3f3f;
     87         if (v==3) ans=0,flag=0;
     88         if (ql<=mid)
     89         {
     90             if (v==1) ans=max(ans,query(a[x].ls));
     91             if (v==2) ans=min(ans,query(a[x].ls));
     92             if (v==3) ans=query(a[x].ls),flag=1;
     93         }
     94         if (qr>mid)
     95         {
     96             if (v==1) ans=max(ans,query(a[x].rs));
     97             if (v==2) ans=min(ans,query(a[x].rs));
     98             if (v==3)
     99             {
    100                 if (flag) ans=gcd(ans,gcd(query(a[x].rs),fabs(num[a[a[x].rs].l]-num[a[a[x].ls].r])));
    101                 else ans=query(a[x].rs);
    102             }
    103         }
    104         return ans;
    105     }
    106     int query(int L,int R,int v)
    107     {
    108         if (L>R) return 0;
    109         ql=L;qr=R;this->v=v;
    110         return query(1);
    111     }
    112 }t;
    113 struct SMT2
    114 {
    115     struct Node
    116     {
    117         int Max;
    118         int l,r;
    119         int ls,rs;
    120     }a[maxn<<1];
    121     int size;
    122     SMT2() {size=0;}
    123     void up(int x)
    124     {
    125         const int &p=a[x].ls,&q=a[x].rs;
    126         a[x].Max=max(a[p].Max,a[q].Max);
    127     }
    128     void build(int &x,int L,int R)
    129     {
    130         x=++size;
    131         a[x].l=L;a[x].r=R;
    132         if (a[x].l==a[x].r)
    133         {
    134             a[x].ls=a[x].rs=0;
    135             a[x].Max=pre[L];
    136             return;
    137         }
    138         const int mid=(L+R)>>1;
    139         build(a[x].ls,L,mid);
    140         build(a[x].rs,mid+1,R);
    141         up(x);
    142     }
    143     void build() {int x;build(x,1,n);}
    144     int ql,qr,v;
    145     void modify(int x)
    146     {
    147         if (a[x].l==a[x].r) a[x].Max=v;
    148         else
    149         {
    150             const int mid=(a[x].l+a[x].r)>>1;
    151             if (ql<=mid) modify(a[x].ls);
    152             else modify(a[x].rs);
    153             up(x);
    154         }
    155     }
    156     void modify(int x,int v)
    157     {
    158         ql=x;this->v=v;
    159         modify(1);
    160     }
    161     int query(int x)
    162     {
    163         if (ql<=a[x].l && a[x].r<=qr) return a[x].Max;
    164         const int mid=(a[x].l+a[x].r)>>1;
    165         int ans=-1;
    166         if (ql<=mid) ans=max(ans,query(a[x].ls));
    167         if (qr> mid) ans=max(ans,query(a[x].rs));
    168         return ans;
    169     }
    170     int query(int L,int R)
    171     {
    172         if (L>R) return 0x3f3f3f3f;
    173         ql=L;qr=R;
    174         return query(1);
    175     }
    176 }tpre;
    177 int lisan[maxn<<1],li=0;
    178 #define maxh 1000007
    179 int first[maxh],Next[maxn<<1];
    180 int getid(int x)
    181 {
    182     int v=x%maxh;
    183     for (int i=first[v];i;i=Next[i])
    184         if (lisan[i]==x) return i;
    185     lisan[++li]=x;
    186     Next[li]=first[v];
    187     first[v]=li;
    188     return li;
    189 }
    190 bool isdigit(char c) {return c>='0' && c<='9';}
    191 int qread()
    192 {
    193     char c;int s=0;while (!isdigit(c=getchar()));
    194     do s=s*10+c-'0'; while (isdigit(c=getchar()));return s;
    195 }
    196 int main()
    197 {
    198     scanf("%d%d",&n,&m);
    199     memset(first,0,sizeof(first));
    200     for (int i=1;i<=n;i++) num[i]=qread();
    201     for (int i=1;i<=m;i++)
    202     {
    203         doo[i].id=qread();
    204         if (doo[i].id==1) doo[i].x=qread(),doo[i].y=qread();
    205         else doo[i].x=qread(),doo[i].y=qread(),doo[i].z=qread();
    206     }
    207     for (int i=1;i<=n;i++)
    208     {
    209         int pos=getid(num[i]);
    210         if (s[pos].begin()!=s[pos].end()) {It it=s[pos].end();pre[i]=*--it;}
    211         else pre[i]=0;
    212         s[pos].insert(i);
    213     }
    214     t.build();
    215     tpre.build();
    216     int yes=0;
    217     for (int i=1;i<=m;i++)
    218         if (doo[i].id==1)
    219         {
    220             int x=doo[i].x^yes,y=doo[i].y^yes;
    221             int p=getid(num[x]);
    222             It it=s[p].lower_bound(x);
    223             if (++it!=s[p].end()) tpre.modify(*it,tpre.query(x,x));it--;
    224             s[p].erase(it);
    225             p=getid(y);
    226             s[p].insert(x);
    227             it=s[p].lower_bound(x);
    228             if (it!=s[p].begin()) tpre.modify(x,*--it),it++;
    229             else tpre.modify(x,0);
    230             if (++it!=s[p].end()) tpre.modify(*it,x);
    231             num[x]=y;
    232             t.modify(x,y);
    233         }
    234         else
    235         {
    236             int x=doo[i].x^yes,y=doo[i].y^yes,z=doo[i].z^yes;
    237             int Max=t.query(x,y,1),Min=t.query(x,y,2);
    238             if (!z)
    239             {
    240                 if (Max!=Min) puts("No");
    241                 else puts("Yes"),yes++;
    242             }
    243             else if (x==y) puts("Yes"),yes++;
    244             else if (Max-Min!=1ll*(y-x)*z) puts("No");
    245             else if (t.query(x,y,3)!=z) puts("No");
    246             else if (tpre.query(x,y)>=x) puts("No");
    247             else puts("Yes"),yes++;
    248         }
    249     return 0;
    250 }
    View Code

    文艺做法:我们是希望这一段和等差数列尽可能接近,而最大值和最小值就可以确定等差数列的每一项,然后?序列hash!一个hash值不能确保两序列相同,那就和,平方和,立方和,等等,一起算看一不一样即可。

    代码自行yy。

  • 相关阅读:
    树莓派:2安装MySQL
    树莓派:1组装启动
    NLifeBill第六章月总额报表
    NLifeBill第五章修改页面
    NLifeBill第四章添加页面
    NLifeBill第三章Angularjs使用
    NLifeBill第二章日历显示
    NLifeBill第一章项目搭建
    『ORACLE』 SQL语句简单应用(二)(11g)
    『ORACLE』 SQL语句简单使用(一)(11g)
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7697650.html
Copyright © 2011-2022 走看看