BZOJ 2333 [SCOI2011]棘手的操作
2017-08-12 16:57
489 查看
BZOJ 2333 [SCOI2011]棘手的操作
线段树,离线,图论题意
给你N个点,每点开始时是独立的,有点权。设计数据结构支持:
加边,将点x,点y连通
修改单点权值、修改整体权值、修改某一点所在连通块的权值
查询单点权值、查询整体最大权值、查询某一点所在连通块的最大权值
思路
%%%因为两个连通块合并后就不会被拆开,所以考虑离线。处理出最后的树,进行dfs序,对每个点重新标号。这样就把连通块变成了区间操作,线段树维护最大值即可。
关于重新标号:用三个数组维护,fa表示某个点所在连通块得第一个节点;ne表示某个点的后继节点(独立点或某块的最后一点为0);la只对某一连通块的第一个点有效,表示该连通块的最后一个点。在联通块内用ne数组遍历标号。
预处理dfs序标号到ha数组。查询时,重做一遍,查询某个点的连通块相当于查询
query(ha[getfa(x)], ha[la[getfa(x)]], 1, n, 1))
代码
#include <bits/stdc++.h> #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define M(a,b) memset(a,b,sizeof(a)) using namespace std; const int MAXN=300007; const int oo=0x3f3f3f3f; int haval[MAXN], val[MAXN], ha[MAXN]; //询问 struct Query { int op;int x, y; Query() { op=x=y=0; } inline void read() { char tmp[5];scanf("%s", tmp); if(tmp[0]=='U') scanf("%d%d", &x, &y), op=1; else if(tmp[0]=='A') { if(tmp[1]=='1') scanf("%d%d", &x, &y), op=2;//单点修改 if(tmp[1]=='2') scanf("%d%d", &x, &y), op=3;//联通块修改 if(tmp[1]=='3') scanf("%d", &x), op=4;//整体修改 } else if(tmp[0]=='F') { if(tmp[1]=='1') scanf("%d", &x), op=5;//单点查询 if(tmp[1]=='2') scanf("%d", &x), op=6;//联通块查询 if(tmp[1]=='3') op=7;//整体查询 } } }q[MAXN]; //并查集 int fa[MAXN], ne[MAXN], la[MAXN]; inline void init(int n) { for(int i=1;i<=n;i++) fa[i]=la[i]=i;M(ne, 0); } int getfa(int x) { return fa[x]==x ? x : fa[x]=getfa(fa[x]); } //线段树 struct STREE { int maxval, lazy; }stree[MAXN<<2]; inline void pushup(int rt) { stree[rt].maxval=max(stree[rt<<1].maxval, stree[rt<<1|1].maxval); } inline void pushdown(int rt) { if(stree[rt].lazy!=0) { stree[rt<<1].maxval+=stree[rt].lazy; stree[rt<<1|1].maxval+=stree[rt].lazy; stree[rt<<1].lazy+=stree[rt].lazy; stree[rt<<1|1].lazy+=stree[rt].lazy; stree[rt].lazy=0; } } void build(int l, int r, int rt) { stree[rt].lazy=0; if(l==r) { stree[rt].maxval=haval[l]; return; } int mid=(l+r)>>1; build(lson), build(rson); pushup(rt); } void update(int L, int R, int v, int l, int r, int rt) { if(L<=l&&r<=R) { stree[rt].maxval+=v; stree[rt].lazy+=v; return; } pushdown(rt); int mid=(l+r)>>1; if(L<=mid) update(L, R, v, lson); if(mid<R) update(L, R, v, rson); pushup(rt); } int query(int L, int R, int l, int r, int rt) { if(L<=l&&r<=R) return stree[rt].maxval; pushdown(rt); int mid=(l+r)>>1, res=-oo; if(L<=mid) res=max(res, query(L, R, lson)); if(mid<R) res=max(res, query(L, R, rson)); return res; } int main() { int n; while(scanf("%d", &n)==1) { init(n); for(int i=1;i<=n;i++) scanf("%d", &val[i]); int m;scanf("%d", &m); for(int i=1;i<=m;i++) { q[i].read(); if(q[i].op==1) { int x=q[i].x, y=q[i].y; int fx=getfa(x), fy=getfa(y); if(fx!=fy) { fa[fy]=fx;ne[la[fx]]=fy;la[fx]=la[fy]; } } } int cnt=0; for(int i=1;i<=n;i++) if(getfa(i)==i) for(int j=i;j!=0;j=ne[j]) { ha[j]=++cnt;haval[cnt]=val[j]; } build(1, n, 1), init(n); for(int i=1;i<=m;i++) { if(q[i].op==1) { int x=q[i].x, y=q[i].y; int fx=getfa(x), fy=getfa(y); if(fx!=fy) { fa[fy]=fx;ne[la[fx]]=fy;la[fx]=la[fy]; } } else if(q[i].op==2) { int x=q[i].x, v=q[i].y; update(ha[x], ha[x], v, 1, n, 1); } else if(q[i].op==3) { int x=q[i].x, v=q[i].y; int fx=getfa(x); update(ha[fx], ha[la[fx]], v, 1, n, 1); } else if(q[i].op==4) { int v=q[i].x; update(1, n, v, 1, n, 1); } else if(q[i].op==5) { int x=q[i].x; printf("%d\n", query(ha[x], ha[x], 1, n, 1)); } else if(q[i].op==6) { int x=q[i].x; int fx=getfa(x); printf("%d\n", query(ha[fx], ha[la[fx]], 1, n, 1)); } else if(q[i].op==7) { printf("%d\n", query(1, n, 1, n, 1)); } } } return 0; }
相关文章推荐
- [可并堆] BZOJ 2333 [SCOI2011]棘手的操作
- bzoj 2333: [SCOI2011]棘手的操作 离线+线段树
- 【bzoj2333】 SCOI2011—棘手的操作
- (右偏树)Bzoj2333: [SCOI2011]棘手的操作
- 【bzoj2333】 [SCOI2011]棘手的操作 可并堆+lazy标记
- 【bzoj2333】[SCOI2011]棘手的操作 可并堆+set
- BZOJ 2333 SCOI 2011 棘手的操作 可并堆
- [BZOJ2333][SCOI2011]棘手的操作(可并堆||线段树)
- 【BZOJ】2333: [SCOI2011]棘手的操作
- [bzoj2333][SCOI2011][棘手的操作]
- 【BZOJ2333】【SCOI2011】棘手的操作 treap合并
- [BZOJ2333][SCOI2011]棘手的操作
- [BZOJ2333][SCOI2011][可并堆]棘手的操作
- 【左偏树】【bzoj 2333】: [SCOI2011]棘手的操作
- BZOJ 2333 SCOI2011 棘手的操作 可并堆套可并堆
- 【bzoj2333】[SCOI2011]棘手的操作 可并堆+STL-set
- bzoj 2333: [SCOI2011]棘手的操作(线段树+离线操作)
- [bzoj2333] [SCOI2011]棘手的操作 (可并堆)
- 【BZOJ2333】棘手的操作(SCOI2011)-线段树+并查集+离线处理
- 【BZOJ2333】【SCOI2011】棘手的操作 可并堆+堆套堆(什么嘛,用个set就好啦)