题意:有⑨种操作
1.新建一个节点,权值为x。
2.连接两个节点。
3.将一个节点a所属于的联通快内权值小于x的所有节点权值变成x。
4.将一个节点a所属于的联通快内权值大于x的所有节点权值变成x。
5.询问一个节点a所属于的联通块内的第k小的权值是多少。
6.询问一个节点a所属联通快内所有节点权值之积与另一个节点b所属联通快内所有节点权值之积的大小。
7.询问a所在联通快内节点的数量
8.若两个节点a,b直接相连,将这条边断开。
9.若节点a存在,将这个点删去。
0<=m<=400000,权值<=1000000000,c<=7
动态图问题(大嘘)
8和⑨操作并不存在。于是由于没有单点修改,比BZOJ2333还要简单。
查询第k大的时候忘了一路下推标记WA了一下午。。。
想刷点水题都刷不动,orz
代码:
#include<cstdio>
#include<cmath>
#include<cassert>
#include<tr1/random>
#define gm 400001
using namespace std;
struct Istream
{
static const size_t str=1<<16;
char buf[str],*s,*t;
Istream():buf(),s(),t(){}
char get() {return (s==t)?(t=buf+fread(s=buf,1,str,stdin),*s++):(*s++);}
Istream& operator>> (int &x)
{
x=0;register char c;
do c=get(); while(c<'0'||c>'9');
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=get();
return *this;
}
}cin;
struct Ostream
{
static const size_t str=1<<16;
char buf[str],*s,*t;
Ostream():buf(),s(buf),t(buf+str){}
~Ostream(){fwrite(buf,1,s-buf,stdout);}
void put(char c){(s==t)?(fwrite(s=buf,1,str,stdout),*s++=c):(*s++=c);}
Ostream& operator<< (int x)
{
if(!x) put('0');
else
{
int a[15],t=1;
while(x) a[t++]=x%10,x/=10;
while(--t) put(a[t]+'0');
}
return *this;
}
Ostream& operator<< (const char *x)
{
while(*x) put(*x++);
return *this;
}
}cout;
const char *endl="\n";
int m;
namespace Treap
{
tr1::mt19937 rnd;
struct node
{
node *l,*r;
int v,w,mark,sz;
double vx,sum;
node(int x):l(),r(),v(x),w(rnd()),mark(),sz(1),vx(log2(x)),sum(vx){}
void cast(int x,const double& __logx)
{
v=mark=x;
vx=__logx,sum=__logx*sz;
}
void down()
{
if(mark)
{
if(l) l->cast(mark,vx);
if(r) r->cast(mark,vx);
mark=0;
}
}
void up()
{
sz=1,sum=vx;
if(l) sz+=l->sz,sum+=l->sum;
if(r) sz+=r->sz,sum+=r->sum;
}
};
struct pair
{
node *fi,*se;
pair(node *fi=0,node *se=0):fi(fi),se(se){}
};
struct treap
{
private:
node *rt;
static pair split(node *a,int v)
{
if(!a) return pair();
a->down();
if(a->v<=v)
{
pair res=split(a->r,v);
a->r=res.fi;
a->up();
return pair(a,res.se);
}
else
{
pair res=split(a->l,v);
a->l=res.se;
a->up();
return pair(res.fi,a);
}
}
static node* merge(node *a,node *b)
{
if(!a) return b;
if(!b) return a;
if(a->w>b->w)
{
a->down();
a->r=merge(a->r,b);
a->up();
return a;
}
else
{
b->down();
b->l=merge(a,b->l);
b->up();
return b;
}
}
static node *join(node *a,node *b)
{
if(!a) return b;
if(!b) return a;
if(a->w>b->w)
{
pair p=split(b,a->v);
a->down();
a->l=join(a->l,p.fi);
a->r=join(a->r,p.se);
a->up();
return a;
}
else
{
pair p=split(a,b->v);
b->down();
b->l=join(b->l,p.fi);
b->r=join(b->r,p.se);
b->up();
return b;
}
}
public:
treap():rt(){}
treap(int x):rt(new node(x)){}
void join(treap &rhs)
{
rt=join(rt,rhs.rt);rhs.rt=0;
}
void lower_limit(int x)
{
pair p=split(rt,x-1);
if(p.fi) p.fi->cast(x,log2(x));
rt=merge(p.fi,p.se);
}
void upper_limit(int x)
{
pair p=split(rt,x);
if(p.se) p.se->cast(x,log2(x));
rt=merge(p.fi,p.se);
}
int find_by_order(int k)
{
node *x=rt;
while(x)
{
x->down();
int cnt=(x->l)?(x->l->sz):0;
if(k==cnt+1) return x->v;
if(k<=cnt) x=x->l;
else k-=cnt+1,x=x->r;
}
assert(0);
}
bool operator < (const treap &rhs) const
{
return rt->sum<rhs.rt->sum;
}
int size()
{
return rt->sz;
}
};
}
struct union_set
{
private:
int r[gm];
int tot;
public:
union_set():r(),tot(){}
int push_back()
{
return r[++tot]=tot;
}
int find(int x)
{
return r[x]==x?x:r[x]=find(r[x]);
}
void set(int x,int y)
{
r[x]=y;
}
}s;
typedef Treap::treap tree;
tree t[gm];
int main()
{
cin>>m;
while(m--)
{
int a,b,c;
cin>>c>>a;
if(c!=1&&c!=7) cin>>b;
switch(c)
{
case 1:
b=s.push_back();
t[b]=tree(a);
break;
case 2:
a=s.find(a),b=s.find(b);
if(a!=b)
{
s.set(a,b);
t[b].join(t[a]);
}
break;
case 3:
a=s.find(a);
t[a].lower_limit(b);
break;
case 4:
a=s.find(a);
t[a].upper_limit(b);
break;
case 5:
a=s.find(a);
cout<<t[a].find_by_order(b)<<endl;
break;
case 6:
a=s.find(a),b=s.find(b);
cout<<int(t[b]<t[a])<<endl;
break;
default:
a=s.find(a);
cout<<t[a].size()<<endl;
}
}
return 0;
}