hdu 4680 splay,启发式合并
这个题是按照权值建树,一般的区间树操作可能得修改一下。
几个操作也很有想法:
1.合并两个集合。这里用到启发式合并的方式,也就是把小的集合一个个插到大的上,
可以证明合并操作不会超过O(nlogn)级别次。
2.拔、插。这是splay的基础不用说了。
3.改。因为是权值建树,不能直接改。先拔出来改了再插回去。
4.这个很巧妙,取最多的点最优的方式肯定是从小到大取,后一个要大于前两个的和。
这样取的数值会增加一倍,这样不超过logn次,暴力搞即可。
这个题是按照权值建树,一般的区间树操作可能得修改一下。
几个操作也很有想法:
1.合并两个集合。这里用到启发式合并的方式,也就是把小的集合一个个插到大的上,
可以证明合并操作不会超过O(nlogn)级别次。
2.拔、插。这是splay的基础不用说了。
3.改。因为是权值建树,不能直接改。先拔出来改了再插回去。
4.这个很巧妙,取最多的点最优的方式肯定是从小到大取,后一个要大于前两个的和。
这样取的数值会增加一倍,这样不超过logn次,暴力搞即可。
5.区间的gcd。也是splay的基础操作。把区间转到一个子树上,求根的值即可。
所以总的就是O(nlognlogn)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define NN 310010
const int inf=2000001000;
int getgcd(int a,int b){
int t;
while(b){t=a;a=b;b=t%b;}
return a;
}
struct sn{
sn *c[2],*f;
int val;
int size;
int gcd;
int r;
inline void init(){
f=c[0]=c[1]=NULL;
gcd=val=0;
r=0;
size=1;
}
inline void setval(int b){val=gcd=b;}
inline void rot(int d){
sn *y=f,*z=y->f;
y->c[!d]=c[d]; if(c[d]) c[d]->f=y;
f=z; if(z) if(y==z->c[0]) z->c[0]=this; else z->c[1]=this;
c[d]=y; y->f=this;
y->update();
}
inline void splay(sn *fa){
while(f != fa){
if(f->f == fa) {
if( f->c[0] == this) rot(1);
else rot(0);
}else{
sn *y=f,*z=y->f;
if( y->c[0] == this){
if( z->c[0]==y ) { y->rot(1); rot(1); }
else{ rot(1); rot(0); }
}else{
if( z->c[0]!=y ) { y->rot(0); rot(0); }
else{ rot(0); rot(1); }
}
}
}
update();
}
inline void update(){
size=1;
if (c[0]) size+=c[0]->size;
if (c[1]) size+=c[1]->size;
gcd=val;
if (c[0]) gcd=getgcd(gcd,c[0]->gcd);
if (c[1]) gcd=getgcd(gcd,c[1]->gcd);
}
inline sn* select(int r){ //按左右序第r个
//push_down();
int cnt=0; if( c[0] ) cnt+=c[0]->size;
if( r<=cnt ) return c[0]->select(r);
if( r==cnt+1) return this;
return c[1]->select(r-cnt-1);
}
}tp[NN],*root[NN];
int tn; //初始化
sn* _alloc() { tp[++tn].init(); return &tp[tn];}
sn* lower_bound(sn *root,int val){ //first >=val
sn *ret=NULL,*p=root;
while(p){
if (val<=p->val&&(!ret||p->val<=ret->val)){
ret=p;
}
if (p->val>=val) p=p->c[0];
else p=p->c[1];
}
return ret;
}
sn* upper_bound(sn *root,int val){ // first >val
sn *ret=NULL,*p=root;
while(p){
if (val<p->val&&(!ret||p->val<=ret->val)){
ret=p;
}
if (p->val>val) p=p->c[0];
else p=p->c[1];
}
return ret;
}
sn* lower_bound_r(sn *root,int val){ //last <=val
sn *ret=NULL,*p=root;
while(p){
if (val>=p->val&&(!ret||p->val>=ret->val)){
ret=p;
}
if (p->val<=val) p=p->c[0];
else p=p->c[1];
}
return ret;
}
sn* upper_bound_r(sn *root,int val){ //last <val
sn *ret=NULL,*p=root;
while(p){
if (p->val<val&&(!ret||p->val>=ret->val)){
ret=p;
}
if (p->val<val) p=p->c[1];
else p=p->c[0];
}
return ret;
}
//--------------------------------------------------------
void insert(sn *now,int y){
sn *p=root[y];
sn *t1=upper_bound_r(p,now->val);
sn *t2=lower_bound(p,now->val);
t1->splay(NULL);
t2->splay(t1);
t2->c[0]=now;
now->f=t2;
now->r=y;
now->splay(NULL);root[y]=now;
}
void del(sn *p,int x){
p->splay(NULL);
sn* tmp=p->c[1]->select(1);
tmp->splay(p);
tmp->c[0]=p->c[0];p->c[0]->f=tmp;
p->c[0]=p->c[1]=p->f=NULL;
tmp->f=NULL;
tmp->splay(NULL); root[x]=tmp;
}
void dfs(sn *p,int y){
if (p->c[0]) {dfs(p->c[0],y);p->c[0]=NULL;}
if (p->c[1]) {dfs(p->c[1],y);p->c[1]=NULL;}
p->f=NULL;
if (p->val==0||p->val==inf) return;
insert(p,y);
}
int query1(int x){
sn *p=root[x],*p1,*p2;
if (root[x]->size<=4) return root[x]->size-2;
p1=lower_bound(p,1);
p2=upper_bound_r(p,p1->val+1);
int now,last,ret;
if (p1!=p2){
now=p2->val;
last=p1->val;
ret=2;
}
else {
now=p2->val;
last=1;
ret=1;
}
while(1){
if (now==inf) break;
p1=lower_bound(p,now+last);
ret++;
last=now;
now=p1->val;
}
return ret-1;
}
int query2(int x,int l,int r){
sn *p=root[x],*p1,*p2;
p2=upper_bound(p,r);
p1=upper_bound_r(p,l);
p1->splay(NULL);root[x]=p1;
p2->splay(p1);
if (!p2->c[0]) return -1;
else return p2->c[0]->gcd;
}
int h[NN/3];
sn* ptr[NN/3];
void init_splay(int n){
tn=-1;
int i;
sn *p;
for(i=1;i<=n;++i){
ptr[i]=_alloc();
ptr[i]->setval(h[i]);
ptr[i]->r=i;
root[i]=ptr[i];
p=_alloc();
p->setval(0);
ptr[i]->c[0]=p;p->f=ptr[i];
p=_alloc();
p->setval(inf);
ptr[i]->c[1]=p;p->f=ptr[i];
ptr[i]->update();
}
}
int main(){
//freopen("4680in.txt","r",stdin);
int tcas,cas;
int i,m,n;
int a,b,c,f,x,y;
int t1,t2;
sn *tmp,*tt,*tt2;
char s[20];
scanf("%d",&tcas);
for(cas=1;cas<=tcas;++cas){
scanf("%d%d",&n,&m);
for(i=1;i<=n;++i){
scanf("%d",&h[i]);
}
init_splay(n);
printf("Case #%d:\n",cas);
for(i=1;i<=m;++i){
scanf("%d",&f);
if (f==1){
scanf("%d%d",&a,&b);
x=ptr[a]->r;y=ptr[b]->r;
if (x==y) continue;
if (root[x]->size>root[y]->size){
swap(x,y);
swap(a,b);
}
dfs(root[x],y);
}
else if(f==2){
scanf("%d%d",&a,&b);
x=ptr[a]->r;y=ptr[b]->r;
del(ptr[a],x);
insert(ptr[a],y);
ptr[a]->r=y;
}
else if(f==3){
scanf("%d%d",&a,&b);
x=ptr[a]->r;
del(ptr[a],x);
ptr[a]->setval(b);
insert(ptr[a],x);
}
else if(f==4){
scanf("%d",&a);
x=ptr[a]->r;
printf("%d\n",query1(x));
}
else if (f==5){
scanf("%d%d%d",&a,&b,&c);
x=ptr[a]->r;
printf("%d\n",query2(x,b,c));
}
}
}
return 0;
}