一眼分块题……

分块,维护每个块的总的gcd和xor和

先思考我们应该怎么查询,考虑到gcd是一个神奇的东西,因为它最多变化logX次

于是我们从前往后扫描每个块,如果一个块内总的gcd是当前扫描的前缀gcd的倍数

那么,也就意味着这个块里的每个位置所对应的前缀的gcd都等于当前gcd

因此,我们设当前xor和为nowxor,gcd为nowgcd,partxor为块内某个块前缀xor和

nowxor xor partxor*nowgcd=x 即 nowxor xor (x/nowgcd)=partxor

这时候只要查询块内是否存在某个块前缀xor和为nowxor xor (x/nowgcd)即可,这我们可以用hash解决

如果不是倍数关系,那么我们直接暴力这个块即可,这样的暴力一定不会超过logX次

至于修改,我们直接暴力重构对应块即可

  1 const mo=124367;
  2 type node=record
  3        po,num,next:longint;
  4      end;
  5 
  6 var e:array[0..6010010] of node;
  7     p:array[0..320,0..mo] of longint;
  8     a,g,b,be:array[0..100010] of longint;
  9     size,t,len,i,j,n,m,x,y:longint;
 10     z:int64;
 11     ch:char;
 12     s:string;
 13 
 14 function gcd(a,b:longint):longint;
 15   begin
 16     if b=0 then exit(a)
 17     else exit(gcd(b,a mod b));
 18   end;
 19 
 20 function min(a,b:longint):longint;
 21   begin
 22     if a>b then exit(b) else exit(a);
 23   end;
 24 
 25 procedure work(x,y,z:longint);
 26   var i,j:longint;
 27   begin
 28     i:=p[x,y mod mo];
 29     while i<>0 do
 30     begin
 31       j:=e[i].po;
 32       if e[i].po=y then
 33       begin
 34         e[i].num:=min(e[i].num,z);
 35         exit;
 36       end;
 37       i:=e[i].next;
 38     end;
 39     inc(len);
 40     e[len].po:=y;
 41     e[len].num:=z;
 42     e[len].next:=p[x,y mod mo];
 43     p[x,y mod mo]:=len;
 44   end;
 45 
 46 procedure del(x,y,z:longint);
 47   var i,j:longint;
 48   begin
 49      i:=p[x,y mod mo];
 50     while i<>0 do
 51     begin
 52       j:=e[i].po;
 53       if e[i].po=y then
 54       begin
 55         if e[i].num=z then e[i].num:=n+1;
 56         exit;
 57       end;
 58       i:=e[i].next;
 59     end;
 60   end;
 61 
 62 function get(x,y:longint):longint;
 63   var i,j:longint;
 64   begin
 65     i:=p[x,y mod mo];
 66     while i<>0 do
 67     begin
 68       j:=e[i].po;
 69       if j=y then exit(e[i].num);
 70       i:=e[i].next;
 71     end;
 72     exit(n+1);
 73   end;
 74 
 75 function ask(x:int64):longint;
 76   var tg,tx,i,j,r,p:longint;
 77   begin
 78     tg:=0; tx:=0;
 79     for i:=1 to size do
 80     begin
 81       tg:=gcd(tg,a[i]);
 82       tx:=tx xor a[i];
 83       if int64(tg)*int64(tx)=x then exit(i);
 84       if x div int64(tg)>1 shl 30 then exit(-1);
 85     end;
 86     for i:=2 to t do
 87     begin
 88       if x div int64(tg)>1 shl 30 then exit(-1);
 89       if i=t then r:=n else r:=i*size;
 90       if g[r] mod tg=0 then
 91       begin
 92         if x mod tg=0 then
 93         begin
 94           p:=get(i,tx xor (x div int64(tg)));
 95           if p<=n then exit(p);
 96         end;
 97         tx:=tx xor b[r];
 98       end
 99       else begin
100         for j:=(i-1)*size+1 to r do
101         begin
102           tg:=gcd(tg,a[j]);
103           tx:=tx xor a[j];
104           if int64(tg)*int64(tx)=x then exit(j);
105           if x div int64(tg)>1 shl 30 then exit(-1);
106         end;
107       end;
108     end;
109     exit(-1);
110   end;
111 
112 begin
113   readln(n);
114   size:=trunc(sqrt(n));
115   for i:=1 to n do
116   begin
117     read(a[i]);
118     be[i]:=(i-1) div size+1;
119   end;
120   t:=n div size;
121   if n mod size<>0 then inc(t);
122   for i:=1 to n do
123   begin
124     if i mod size=1 then
125     begin
126       g[i]:=a[i];
127       b[i]:=a[i];
128     end
129     else begin
130       b[i]:=b[i-1] xor a[i];
131       g[i]:=gcd(g[i-1],a[i]);
132     end;
133     work(be[i],b[i],i);
134   end;
135   readln(m);
136   for i:=1 to m do
137   begin
138     s:='';
139     read(ch);
140     while ch<>' ' do
141     begin
142       s:=s+ch;
143       read(ch);
144     end;
145     if s[1]='M' then
146     begin
147       readln(x,y);
148       inc(x);
149       a[x]:=y;
150       for j:=x to min(size*be[x],n) do
151       begin
152         del(be[x],b[j],j);
153         if j mod size=1 then
154         begin
155           b[j]:=a[j];
156           g[j]:=a[j];
157         end
158         else begin
159           b[j]:=b[j-1] xor a[j];
160           g[j]:=g[j-1] xor a[j];
161         end;
162         work(be[x],b[j],j);
163       end;
164     end
165     else begin
166       readln(z);
167       x:=ask(z);
168       if x=-1 then writeln('no') else writeln(x-1);
169     end;
170   end;
171 end.
View Code

 

posted on 2015-05-10 21:56  acphile  阅读(202)  评论(0编辑  收藏  举报