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; }
相关文章推荐
- bzoj2333 [SCOI2011]棘手的操作
- BZOJ2333: [SCOI2011]棘手的操作
- bzoj2333 [SCOI2011]棘手的操作
- bzoj千题计划218:bzoj2333: [SCOI2011]棘手的操作
- bzoj2333[SCOI2011]棘手的操作
- bzoj2333 [SCOI2011]棘手的操作
- bzoj2333 [SCOI2011]棘手的操作
- bzoj2333: [SCOI2011]棘手的操作 线段树+离线
- bzoj2333: [SCOI2011]棘手的操作
- 真--可并堆模板--BZOJ2333: [SCOI2011]棘手的操作
- 【BZOJ2333】【SCOI2011】棘手的操作 treap合并
- BZOJ2333: [SCOI2011]棘手的操作
- BZOJ2333: [SCOI2011]棘手的操作
- bZOJ2333 【scoi2011】棘手的操作
- bzoj2333[SCOI2011]棘手的操作
- BZOJ2333 [SCOI2011]棘手的操作 【离线 + 线段树】
- bzoj千题计划217:bzoj2333: [SCOI2011]棘手的操作
- bzoj2333 [SCOI2011]棘手的操作
- [BZOJ2333][SCOI2011]棘手的操作(可并堆||线段树+离线)
- 【bzoj2333】 SCOI2011—棘手的操作