BZOJ4028 [HEOI2015] convention number series block

Given a sequence, the following two operations are required:
1. Single point modification
2. Find the first position p in the sequence so that the prefix gcd * prefix xor and xor = = an input number x

Consider fragmentation + violence
The prefixes gcd and xor of each block are calculated according to n √ block
Update gcd and xor violently to the block in single point modification
The complexity of each update is n √ logn

Two situations of query time

① If gcd (gcd ﹣ now, gcd ﹣ pre) = = gcd ﹣ pre, that is, until the end of the current block, gcd does not change
The current block prefix gcd is unique, so the matching prefix xor value is also unique.
In this block, it is enough to find the existence of dichotomy

② If gcd is not equal, scan the answer to this block from beginning to end
However, since gcd changes logn times at most, the complexity here is also n √ logn

The total complexity does not exceed O(nn √ logn)

It's as complicated as it is.. When I think about it, I didn't expect to inquire
Upper code

#include<bits/stdc++.h>
#define LL long long
#define clr(x,i) memset(x,i,sizeof(x))
using namespace std;
const int N=100005;
inline void read(LL &x)
{
    x=0;char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
}
struct data{
    LL xt,id;
    friend bool operator <(data a,data b){
        return a.xt==b.xt ? a.id<b.id : a.xt<b.xt;
    }
}b[N];
LL n,q,a[N],gs[N],xs[N];
int id[N],l[666],r[666],tim,tot;

LL GCD(LL a,LL b)
{
    if(!b)return a;
    return GCD(b,a%b);
}
void work(int x)
{
    int be=l[x],en=r[x];
    gs[be]=xs[be]=b[be].xt=a[be];
    b[be].id=be;
    for(int i=be+1;i<=en;i++){
        gs[i]=GCD(gs[i-1],a[i]);
        xs[i]=xs[i-1]^a[i];
        b[i].xt=xs[i];b[i].id=i;
    }
    sort(b+be,b+en+1);
}
int find(LL x,int l,int r)
{
    int mid,ans=l;
    while(l<=r){
        mid=(l+r)>>1;
        if(b[mid].xt>=x)
          ans=mid,r=mid-1;
        else
          l=mid+1;
    }
    return ans;
}
int main()
{
    read(n);
    tim=sqrt((double)n);tot=(int)(n-1)/tim+1;
    //printf("%d %d\n",tim,tot);
    for(int i=1;i<=n;i++)read(a[i]);
    for(int i=1;i<=n;i++){
        id[i]=(i-1)/tim+1;
        if(!l[id[i]])l[id[i]]=i;
        r[id[i]]=i;
    }
    for(int i=1;i<=tot;i++)
      work(i);
    read(q);
    while(q--)
    {
        char op[10];LL x,y;
        scanf("%s",op);
        if(op[0]=='M'){
            read(x);read(y);x++;
            a[x]=y;
            work(id[x]);
        }
        else{
            read(x);
            LL gl=a[1],xl=0,flag=0;
            for(int i=1;i<=tot&&!flag;i++)
            {
                int be=l[i],en=r[i];
                if(GCD(gs[en],gl)==gl)
                {
                    if(x%gl==0){
                        LL xans=(x/gl)^xl;
                        int pos=find(xans,be,en);
                        if(b[pos].xt==xans){
                            printf("%d\n",b[pos].id-1);flag=1;break;
                        }
                        //
                    }
                    xl^=xs[en];//gl=GCD(gl,gs[en]);
                }
                else{
                    for(int j=be;j<=en;j++)
                    {
                        gl=GCD(gl,a[j]);xl^=a[j];
                        if(gl*xl==x){
                            printf("%d\n",j-1);flag=1;break;
                        }
                    }
                    if(flag)break;
                }

            }
            if(!flag)printf("no\n");
        }
    }
    return 0;
}

The formula has been suspended before. Please send it again

Posted by watsmyname on Fri, 01 May 2020 13:43:45 -0700