链接
http://www.lydsy.com/JudgeOnline/problem.php?id=2333
题解
网上的题解怎么都是可并堆啊,好厉害的样子,我不会… 这题可以启发式合并,每个并查集的根节点维护一个堆,然后启发式合并搞搞就好啦。 其中维护堆的部分我们可以搞一个修改标记表示这个堆里的所有元素都被加了几,没啥好说的了吧.. 时间复杂度
O(Nlog2N)
。
代码
//启发式合并+堆+并查集
using namespace std;
int N, Q, f[maxn], V, d[maxn], a[maxn], vis[maxn];
struct data{
int id, w;data(
int a,
int b):id(a),w(b){}data(){}}stack[maxn];
heap<data> h[maxn], big;
bool operator<(const data &a, const data &b){
return a.w<b.w;}
int find(
int x){
return f[
x]==
x?
x:f[
x]=find(f[
x]);}
inline void upd(
int x)
{
if(
x)
while(a[h[
x].top().id]^h[
x].top().w)h[
x].
pop();
else while(h[big.top().id].empty()
or
h[big.top().id].top().w+d[big.top().id]!=big.top().w)big.
pop();
}
inline void merge(
int x,
int y)
{
int fx=find(
x), fy=find(
y);
if(fx==fy)
return;
if(h[fx].size()>h[fy].size())swap(fx,fy);
for(;!h[fx].empty();h[fx].
pop())
if(h[fx].top().w==a[h[fx].top().id]
and vis[h[fx].top().id]!=Q)
h[fy].
push(data(h[fx].top().id,h[fx].top().w+d[fx]-d[fy])),
a[h[fx].top().id]+=d[fx]-d[fy], vis[h[fx].top().id]=Q;
f[fx]=fy;
upd(fy);
big.
push(data(fy,h[fy].top().w+d[fy]));
upd(
0);
}
inline
int read(
int x=
0)
{
char c=getchar(); bool f=
0;
while(c<
48 or c>
57)f=f
or c==
'-', c=getchar();
while(c>=
48 and c<=
57)
x=(
x<<
1)+(
x<<
3)+c-
48, c=getchar();
return f?-
x:
x;
}
int main()
{
char type[
5];
int x, v, i, fx;
scanf(
"%d",&N);
for(i=
1;i<=N;i++)
scanf(
"%d",a+i), f[i]=i, h[i].
push(data(i,a[i])), big.
push(data(i,a[i]));
scanf(
"%d",&Q);
for(Q++;Q^
1;Q--)
{
scanf(
"%s",type);
if(
*type==
'U')
x=
read(), v=
read(), merge(
x,v);
if(
*type==
'A')
{
if(type[
1]==
'1')
{
x=
read(), v=
read();
a[
x]+=v;
h[fx=find(
x)].
push(data(
x,a[
x]));
upd(fx);
big.
push(data(fx,h[fx].top().w+d[fx]));
upd(
0);
}
if(type[
1]==
'2')
{
x=
read(), v=
read();
d[fx=find(
x)]+=v;
big.
push(data(fx,h[fx].top().w+d[fx]));
upd(
0);
}
if(type[
1]==
'3')d[
0]+=
read();
}
if(
*type==
'F')
{
if(type[
1]==
'1')
x=
read(),
printf(
"%d\n",a[
x]+d[find(
x)]+d[
0]);
if(type[
1]==
'2')
x=
read(),
printf(
"%d\n",h[find(
x)].top().w+d[find(
x)]+d[
0]);
if(type[
1]==
'3')
printf(
"%d\n",big.top().w+d[
0]);
}
}
return 0;
}