您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: