您的位置:首页 > 其它

bzoj2333: [SCOI2011]棘手的操作(启发式合并做法)

2017-05-05 11:14 302 查看

链接

  http://www.lydsy.com/JudgeOnline/problem.php?id=2333

题解

  网上的题解怎么都是可并堆啊,好厉害的样子,我不会…

  这题可以启发式合并,每个并查集的根节点维护一个堆,然后启发式合并搞搞就好啦。

  其中维护堆的部分我们可以搞一个修改标记表示这个堆里的所有元素都被加了几,没啥好说的了吧..

  时间复杂度O(Nlog2N)。

代码

//启发式合并+堆+并查集
#include <cstdio>
#include <algorithm>
#include <queue>
#define heap priority_queue
#define maxn 300005
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: