-by luoguspa
不會啊....code
而後%了一發題解,blog
關鍵是string
考慮序列{$a_n$}的前綴gcd序列,it
它是單調不升的,且最多隻會改變$log_2N$次,由於每變一次至少除2io
因而,當咱們詢問x時:class
對每一段知足前綴gcd不變的部分;效率
能夠用map之類的直接查詢這個區間中前綴xor值等於$x\over gcd$的最小下標;map
但咱們還有單點修改,gc
考慮分塊,——隨便分個根號塊就好
對每塊
維護塊從左端到右端元素的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_2\sqrt{N})$乘上塊數即爲$O(\sqrt{N}log_2\sqrt{N})$
反之,則暴力枚舉這塊中的每一個元素便可,這種狀況不超過log次,其總效率爲$O(\sqrt{N}log_2{N})$
至於修改,則直接把對這塊所維護的信息從新維護便可便可,塊大小爲$\sqrt{N}$乘上map的效率爲$O(\sqrt{N}log_2\sqrt{N})$
因而其總複雜度爲$O(q\sqrt{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\n",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\n",j-1); 97 return ; 98 } 99 } 100 lasgcd=nowgcd,lasxor^=b_xor[i]; 101 } 102 printf("no\n"); 103 }
分塊還差得遠呢