BZOJ 4028 分块

来源:互联网 发布:北方数据 编辑:程序博客网 时间:2024/06/05 11:00

zrt当年是怎么想到的…….
思路:
考虑把序列分块
对于每块 存xor[i] 表示从本块开头到i的前缀异或和
把它扔进set里
存gcd[i]表示从本块开头到i的前缀gcd.
如果这一块的GCD和整个的gcd的gcd是一样的 从set里找ans
否则暴力..
GCD最多log种 所以是复杂度是O(nsqrt(n)logn)的

//By SiriusRen#include <cmath>#include <set>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N=100050;int n,q,a[N],Block,block[N],XOR[N],GCD[N];char op[150];typedef long long ll;set<int>s[320];int gcd(int x,int y){return y?gcd(y,x%y):x;}signed main(){    scanf("%d",&n),Block=sqrt(n);    for(int i=0;i<n;i++)scanf("%d",&a[i]),block[i]=i/Block+1;    for(int i=0;i<n;i++){        if(block[i]==block[i-1])XOR[i]=XOR[i-1]^a[i],GCD[i]=gcd(a[i],GCD[i-1]);        else XOR[i]=a[i],GCD[i]=a[i];        s[block[i]].insert(XOR[i]);    }    scanf("%d",&q);    while(q--){        scanf("%s",op);        if(op[0]=='M'){            int xx,yy;            scanf("%d%d",&xx,&yy),a[xx]=yy;            s[block[xx]].clear();            int tp=lower_bound(block,block+n,block[xx])-block;            XOR[tp]=a[tp],GCD[tp]=a[tp];s[block[xx]].insert(XOR[tp]);            for(int i=tp+1;block[i]==block[tp];i++)                XOR[i]=XOR[i-1]^a[i],GCD[i]=gcd(a[i],GCD[i-1]),s[block[xx]].insert(XOR[i]);        }        else{            ll Q;int Gcd=GCD[lower_bound(block,block+n,2)-block-1],Xor=XOR[lower_bound(block,block+n,2)-block-1];            scanf("%lld",&Q);            for(int i=0;block[i]==1;i++)                if((ll)GCD[i]*XOR[i]==Q){printf("%d\n",i);goto ed;}            for(int i=2;i<=block[n-1];i++){                if(gcd(GCD[upper_bound(block,block+n,i)-block-1],Gcd)!=Gcd){                    int tp=lower_bound(block,block+n,i)-block;                    for(int j=tp;block[j]==block[tp];j++){                        Gcd=gcd(Gcd,a[j]),Xor^=a[j];                        if((ll)Gcd*Xor==Q){printf("%d\n",j);goto ed;}                    }                    continue;                }                ll temp=(Q/Gcd)^Xor;                if(s[i].find(temp)!=s[i].end()){                    int tp=lower_bound(block,block+n,i)-block;                    for(int j=tp;block[j]==block[tp];j++)                        if(XOR[j]==temp){printf("%d\n",j);goto ed;}                }                Xor^=XOR[upper_bound(block,block+n,i)-block-1];            }            puts("no");        }ed:;    }}
0 0
原创粉丝点击