About set HDU - 4680

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:\n",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\n",ans);
234             }
235             else if(idx==5)
236             {
237                 scanf("%d%d%d",&u,&L,&R);
238                 printf("%d\n",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\n",S::q.size());
245     }
246     return 0;
247 }

 

posted @ 2018-07-24 20:56  hehe_54321  阅读(236)  评论(0编辑  收藏  举报
AmazingCounters.com