https://vjudge.net/problem/HDU-4680
一直想写,终于写完了。。。
要点:
这个set不需要去重
操作4的做法就是暴力枚举取的数(最开始两个取set中最小两个,设这次取的值为now,前一次取的值为last,那么下次要取大于等于now+last的最小数),由于每一次取的值大于等于last的值的两倍,因此枚举次数是logn级别的
错误记录:
1.100行少upd
2.多组数据忘消去内存占用
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #include<queue> 6 using namespace std; 7 #define fi first 8 #define se second 9 #define mp make_pair 10 #define pb push_back 11 typedef long long ll; 12 typedef unsigned long long ull; 13 typedef pair<int,int> pii; 14 int n,m; 15 int gcd(int a,int b) 16 { 17 if(!a||!b) return a+b; 18 int t; 19 while(b) 20 { 21 t=a; 22 a=b; 23 b=t%b; 24 } 25 return a; 26 } 27 namespace S 28 { 29 #define N 400100 30 struct Node 31 { 32 Node *ch[2]; 33 int sz,d,r,n; 34 int g; 35 }nds[N]; 36 queue<Node*> q; 37 int rand1() 38 { 39 static int x=233; 40 return x=(48271LL*x+1)%2147483647; 41 } 42 void init() 43 { 44 for(int i=0;i<N;i++) q.push(nds+i); 45 } 46 Node *getnode() 47 { 48 Node *t=q.front();q.pop(); 49 t->ch[0]=t->ch[1]=0;t->sz=t->d=t->g=t->n=0;t->r=rand1(); 50 return t; 51 } 52 void delnode(Node *x) {q.push(x);} 53 int gsz(Node *o) {return o?o->sz:0;} 54 int gg(Node *o) {return o?o->g:0;} 55 void upd(Node *o) 56 { 57 o->g=gcd(gcd(gg(o->ch[0]),o->d),gg(o->ch[1])); 58 o->sz=gsz(o->ch[0])+o->n+gsz(o->ch[1]); 59 } 60 Node *merge(Node *a,Node *b) 61 { 62 if(!a) return b; 63 if(!b) return a; 64 if(a->r<b->r) 65 { 66 a->ch[1]=merge(a->ch[1],b);upd(a); 67 return a; 68 } 69 else 70 { 71 b->ch[0]=merge(a,b->ch[0]);upd(b); 72 return b; 73 } 74 } 75 typedef pair<Node*,Node*> pnn; 76 pnn split_x(Node *a,int x)//<=x,>x 77 { 78 if(!a) return pnn(0,0); 79 pnn y; 80 if(x<a->d) 81 { 82 y=split_x(a->ch[0],x); 83 a->ch[0]=y.se;upd(a);y.se=a; 84 } 85 else 86 { 87 y=split_x(a->ch[1],x); 88 a->ch[1]=y.fi;upd(a);y.fi=a; 89 } 90 return y; 91 } 92 void add(Node *&a,int x,int k) 93 { 94 pnn t1=split_x(a,x-1),t2=split_x(t1.se,x); 95 if(!t2.fi) 96 { 97 Node *t=getnode();t->d=x;upd(t); 98 t2.fi=t; 99 } 100 t2.fi->n+=k;upd(t2.fi);//upd 101 if(t2.fi->n==0) delnode(t2.fi),t2.fi=0; 102 a=merge(t1.fi,merge(t2.fi,t2.se)); 103 } 104 int qg(Node *&a,int l,int r) 105 { 106 pnn t1=split_x(a,l-1),t2=split_x(t1.se,r); 107 int ans=t2.fi?t2.fi->g:-1; 108 a=merge(t1.fi,merge(t2.fi,t2.se)); 109 return ans; 110 } 111 Node *find(Node *a,int x) 112 { 113 if(!a) return 0; 114 if(x<a->d) return find(a->ch[0],x); 115 else if(x==a->d) return a; 116 else return find(a->ch[1],x); 117 } 118 int upb(Node *a,int x) 119 { 120 if(!a) return 0x7fffffff; 121 if(a->d>x) return min(a->d,upb(a->ch[0],x)); 122 else return upb(a->ch[1],x); 123 } 124 void mergeto(Node *&a,Node *b)//b合并到a上 125 { 126 if(!b) return; 127 mergeto(a,b->ch[0]);mergeto(a,b->ch[1]); 128 add(a,b->d,b->n); 129 delnode(b); 130 } 131 void mgto(Node *&a,Node *&b)//b合并到a上,启发式 132 { 133 if(gsz(a)<gsz(b)) swap(a,b); 134 mergeto(a,b); 135 } 136 void deltree(Node *o) 137 { 138 if(!o) return; 139 deltree(o->ch[0]);deltree(o->ch[1]); 140 delnode(o); 141 } 142 } 143 using S::Node; 144 using S::add; 145 using S::upb; 146 Node *rt[N]; 147 int a[N]; 148 namespace D 149 { 150 int fa[N],p[N],num; 151 void init() 152 { 153 int i;num=n; 154 for(i=1;i<=n+m;i++) fa[i]=i,rt[i]=0; 155 for(i=1;i<=n;i++) 156 { 157 p[i]=i; 158 add(rt[i],a[i],1); 159 } 160 } 161 int findd(int x){return x==fa[x]?x:fa[x]=findd(fa[x]);} 162 int find(int x){return findd(p[x]);} 163 void unionn(int x,int y) 164 { 165 x=findd(x);y=findd(y); 166 if(x==y) return; 167 fa[x]=y;S::mgto(rt[y],rt[x]); 168 } 169 void union1(int x,int y){unionn(p[x],p[y]);} 170 void move(int x,int y)//将x移到y所在集合中 171 { 172 if(x==y) return; 173 add(rt[find(x)],a[x],-1); 174 ++num;p[x]=num;unionn(p[x],p[y]); 175 add(rt[find(x)],a[x],1); 176 } 177 void change(int x,int y)//x权值改y 178 { 179 add(rt[find(x)],a[x],-1); 180 a[x]=y; 181 add(rt[find(x)],a[x],1); 182 } 183 } 184 int main() 185 { 186 Node *tt,*r; 187 int T,TT=0,i,ans,u,v,idx,last,now,t,L,R; 188 S::init(); 189 scanf("%d",&T); 190 while(T--) 191 { 192 scanf("%d%d",&n,&m); 193 for(i=1;i<=n;i++) scanf("%d",&a[i]); 194 ++TT; 195 printf("Case #%d: ",TT); 196 D::init(); 197 for(i=1;i<=m;i++) 198 { 199 scanf("%d",&idx); 200 if(idx==1) 201 { 202 scanf("%d%d",&u,&v); 203 D::union1(u,v); 204 } 205 else if(idx==2) 206 { 207 scanf("%d%d",&u,&v); 208 D::move(u,v); 209 } 210 else if(idx==3) 211 { 212 scanf("%d%d",&u,&v); 213 D::change(u,v); 214 } 215 else if(idx==4) 216 { 217 scanf("%d",&u);r=rt[D::find(u)]; 218 if(r->sz<=2) ans=r->sz; 219 else 220 { 221 last=upb(r,-1);tt=S::find(r,last); 222 if(tt->n>1) now=last; 223 else now=upb(r,last); 224 ans=2; 225 while(1) 226 { 227 t=last;last=now; 228 now=upb(r,t+now-1); 229 if(now==0x7fffffff) break; 230 ans++; 231 } 232 } 233 printf("%d ",ans); 234 } 235 else if(idx==5) 236 { 237 scanf("%d%d%d",&u,&L,&R); 238 printf("%d ",S::qg(rt[D::find(u)],L,R)); 239 } 240 } 241 for(i=1;i<=n+m;i++) 242 if(D::findd(i)==i) 243 S::deltree(rt[i]); 244 //printf("%d ",S::q.size()); 245 } 246 return 0; 247 }