zoukankan      html  css  js  c++  java
  • luogu P4108 [HEOI2015]公约数数列——solution

     

     -by luogu



    不会啊....

    然后%了一发题解,

    关键是

    考虑序列{$a_n$}的前缀gcd序列,

    它是单调不升的,且最多只会改变$log_2N$次,因为每变一次至少除2

    于是,当我们询问x时:

    对每一段满足前缀gcd不变的部分;

    可以用map之类的直接查询这个区间中前缀xor值等于$xover gcd$的最小下标;

    但我们还有单点修改,

    考虑分块,——随便分个根号块就好

    对每块

    维护块从左端到右端元素的xor和,

    维护块中左端到右端元素的gcd值,

    对每个元素

    维护从他所在块的左端点到他自己的xor和与gcd值;

    这样修改只影响一块之内的所有元素的相关值和这一块的相关值;

    对每块开个map

    把左端到每个元素的xor值插到对应块的map中去;

    当我们查询x时

    枚举每块,

    如果到这块之前的前缀gcd等于加入这块之后的前缀gcd(设为gcd),则意味着这块之内(从左端到右端)的所有点的前缀gcd都相等,(前缀gcd单调不升)

    这样的话,我们设到这块之前的xor为$XOR_{0,L-1}$我们只需在这块的map中查是否有某个$XOR_{l~i}$值满足$gcd*(XOR_{0,L-1}xorXOR_{l,i})=x$即可,其效率为map的效率,$O(log_2sqrt{N})$乘上块数即为$O(sqrt{N}log_2sqrt{N})$

    反之,则暴力枚举这块中的每个元素即可,这种情况不超过log次,其总效率为$O(sqrt{N}log_2{N})$

    至于修改,则直接把对这块所维护的信息重新维护即可即可,块大小为$sqrt{N}$乘上map的效率为$O(sqrt{N}log_2sqrt{N})$

    于是其总复杂度为$O(qsqrt{N}log_2N)$

    代码:

      1 #include<map>
      2 #include<cmath>
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<algorithm>
      7 #define LL long long
      8 using namespace std;
      9 map <int ,int >MP[350];
     10 int a[100010];
     11 int b_size,b_num;
     12 int L[350];
     13 int b_gcd[350],b_xor[350];
     14 int a_gcd[100010],a_xor[100010];
     15 int n,q;
     16 char s[20];
     17 int GCD(int ,int );
     18 void modify();
     19 void query();
     20 int main()
     21 {
     22     int i,j,k;
     23     scanf("%d",&n);
     24     b_size=sqrt(n);
     25     for(i=1;i<=n;i++)
     26         scanf("%d",&a[i]);
     27     for(b_num=i=1;i<=n;b_num++,i+=b_size){
     28         L[b_num]=i;
     29         a_xor[i]=a_gcd[i]=a[i];
     30         MP[b_num].insert(pair<int ,int >(a_xor[i],i));
     31         for(j=i+1;j<i+b_size&&j<=n;j++){
     32             a_xor[j]=a_xor[j-1]^a[j];
     33             a_gcd[j]=GCD(a_gcd[j-1],a[j]);
     34             MP[b_num].insert(pair<int ,int >(a_xor[j],j));
     35         }
     36         b_xor[b_num]=a_xor[j-1],b_gcd[b_num]=a_gcd[j-1];
     37     }
     38     scanf("%d",&q);
     39     for(i=1;i<=q;i++){
     40         scanf("%s",s);
     41         if(s[0]=='M')
     42             modify();
     43         else
     44             query();
     45     }
     46 }
     47 int GCD(int a,int b){
     48     if(!b)return a;
     49     return GCD(b,a%b);
     50 }
     51 void modify(){
     52     int id,x,i,j,k;
     53     scanf("%d%d",&id,&x),id++;
     54     for(i=j=1;j<=n;j+=b_size,i++)
     55         if(j+b_size>id)
     56             break;
     57     MP[i].clear();
     58     a[id]=x;
     59     a_xor[(i-1)*b_size+1]=a_gcd[(i-1)*b_size+1]=a[(i-1)*b_size+1];
     60     MP[i].insert(pair<int ,int >(a_xor[(i-1)*b_size+1],(i-1)*b_size+1));
     61     for(j=(i-1)*b_size+2;j<=i*b_size&&j<=n;j++){
     62         a_xor[j]=a_xor[j-1]^a[j];
     63         a_gcd[j]=GCD(a_gcd[j-1],a[j]);
     64         MP[i].insert(pair<int ,int >(a_xor[j],j));
     65     }
     66     b_xor[i]=a_xor[j-1],b_gcd[i]=a_gcd[j-1];
     67 }
     68 void query(){
     69     LL x,xx;
     70     map <int ,int >::iterator iter;
     71     int i,j,k,lasxor=0,nowgcd=0,lasgcd=0;
     72     scanf("%lld",&x);
     73     for(i=1;i<=b_num;i++){
     74         nowgcd=GCD(b_gcd[i],lasgcd);
     75         if(nowgcd==lasgcd){
     76             if(x%lasgcd){
     77                 lasgcd=nowgcd,lasxor^=b_xor[i];
     78                 continue;
     79             }
     80             xx=x/lasgcd;
     81             xx^=lasxor;
     82             if(xx>0x7fffffff){
     83                 lasgcd=nowgcd,lasxor^=b_xor[i];
     84                 continue;
     85             }
     86             k=xx;
     87             if(MP[i].count(k)==1){
     88                 iter=MP[i].find(k);
     89                 printf("%d
    ",iter->second-1);
     90                 return ;
     91             }
     92         }
     93         else{
     94             for(j=(i-1)*b_size+1;j<=n&&j<=i*b_size;j++)
     95                 if(1ll*(lasxor^a_xor[j])*GCD(lasgcd,a_gcd[j])==x){
     96                     printf("%d
    ",j-1);
     97                     return ;
     98                 }
     99         }
    100         lasgcd=nowgcd,lasxor^=b_xor[i];
    101     }
    102     printf("no
    ");
    103 }

    分块还差得远呢

  • 相关阅读:
    c++ 连接mysql数据库
    c语言数据结构分析2之 链表插入删除
    c语言数据结构分析1之 链表创建
    微软 翻译工具
    c语言数据结构分析7之 二分查找
    sencha touch2 demo
    程序员装B指南
    c语言数据结构分析6之 快速排序
    c语言数据结构分析5之 冒泡
    对话jQuery之父John Resig:JavaScript的开发之路
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/8568458.html
Copyright © 2011-2022 走看看