• [BZOJ4028][HEOI2015]公约数数列(分块)


    先发掘性质:

    1.xor和gcd均满足交换律与结合率。

    2.前缀gcd最多只有O(log)个。

    但并没有什么数据结构能同时利用这两个性质,结合Q=10000,考虑分块。

    对每块记录这几个信息:

    1.块内所有数的gcd与异或和。

    2.将块内所有前缀异或和放入一个数组排序。

    查询时从前往后遍历每个块:

    1.若当前块不使gcd改变,二分查找是否存在答案。

    2.若改变,暴力查找答案。

    复杂度(设块大小为S,值域为M):

    1.修改复杂度$O(Slog S)$

    2.查询复杂度$O(Slog M+frac{n}{S}log S)$。

    当$S=sqrt{n}$时复杂度最优,为$O(Qsqrt{n}log n)$。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     4 typedef long long ll;
     5 using namespace std;
     6 
     7 const int N=100010,K=410;
     8 char op[10];
     9 int n,B,tot,Q,ans,L[K],R[K];
    10 ll x,k,a[N],G[K],X[K];
    11 struct P{ ll x; int id; }p[N];
    12 bool operator <(const P &a,const P &b){ return (a.x==b.x) ? a.id<b.id : a.x<b.x; }
    13 
    14 ll gcd(ll a,ll b){ return b ? gcd(b,a%b) : a; }
    15 
    16 void build(int x){
    17     G[x]=X[x]=a[L[x]]; p[L[x]]=(P){X[x],L[x]};
    18     rep(j,L[x]+1,R[x]) G[x]=gcd(G[x],a[j]),X[x]^=a[j],p[j]=(P){X[x],j};
    19     sort(p+L[x],p+R[x]+1);
    20 }
    21 
    22 int find(int l,int r,ll k){
    23     while (l<r){
    24         int mid=(l+r)>>1;
    25         if (p[mid].x<k) l=mid+1; else r=mid;
    26     }
    27     return r;
    28 }
    29 
    30 int main(){
    31     freopen("bzoj4028.in","r",stdin);
    32     freopen("bzoj4028.out","w",stdout);
    33     scanf("%d",&n); B=300; tot=(n-1)/B+1;
    34     rep(i,1,n) scanf("%lld",&a[i]);
    35     rep(i,1,tot) L[i]=(i-1)*B+1,R[i]=min(n,i*B),build(i);
    36     for (scanf("%d",&Q); Q--; ){
    37         scanf("%s",op);
    38         if (op[0]=='M') scanf("%lld%lld",&x,&k),x++,a[x]=k,build((x-1)/B+1);
    39         else{
    40             scanf("%lld",&x); ll g=a[1],t=0; bool w=0;
    41             rep(i,1,tot){
    42                 if (gcd(g,G[i])==g){
    43                     if (x%g==0){
    44                         ll k=x/g^t; int ans=find(L[i],R[i],k);
    45                         if (p[ans].x==(x/g^t)){ printf("%d
    ",p[ans].id-1); w=1; break; }
    46                     }
    47                     g=gcd(g,G[i]); t^=X[i];
    48                 }else
    49                     rep(j,L[i],R[i]){
    50                         g=gcd(g,a[j]); t^=a[j];
    51                         if (g*t==x){ printf("%d
    ",j-1); w=1; break; }
    52                     }
    53                 if (w) break;
    54             }
    55             if (!w) puts("no");
    56         }
    57     }
    58     return 0;
    59 }
  • 相关阅读:
    eclipse code templates 设置(eclipse注释模版配置)
    kettle 程序调用执行ktr转换示例代码
    JQuery学习笔记
    获取工程路径(jar和普通文件结构通用) java
    java 获取jar包路径,遍历jar包
    百度跨域ajax
    eclipse Wtp在线安装
    PropertiesHelper
    java base64/jQuery Base64
    Eclipse中,打开文件所在文件夹的插件,及设置
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9882234.html
Copyright © 2020-2023  润新知