您的位置:首页 > 其它

bzoj 2243: [SDOI2011]染色

2017-08-16 00:17 302 查看

bzoj 2243: [SDOI2011]染色

树链剖分,线段树

题意

给定一棵有n个节点的无根树和m个操作,操作有2类:

将节点a到节点b路径上所有点都染成颜色c;

询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。

请你写一个程序依次完成这m个操作。

思路

这种东西。。感觉很套路啊,学会了之后根本不难写,顶多是代码太多写丑了需要调。而且能解决的问题也都很套路。。还是我没碰到高级的问题?

在树上的修改查询,想到树链剖分。我之前一篇Gym的题解说的挺细,不带修改。这题带修改,也没什么区别。修改时也是跟查询一样,往爸爸上跳,直到跳到重链。

啊。。这题,合并查询结果时要注意一下,比如lres有结果,rres没结果,那么返回lres就行,或者合并时把res的右端点给赋值。

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#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=100007;
const int oo=0x3f3f3f3f;

vector<int> G[MAXN];
int Val[MAXN], Hson[MAXN], SonAmount[MAXN], Father[MAXN], Depth[MAXN];
int Dfsnum[MAXN], TreeValue[MAXN], TopOfHeavyChain[MAXN];
int dfscount;

void AddEdge(int from, int to)
{
G[from].push_back(to);
G[to].push_back(from);
}

void dfs1(int n)
{
SonAmount
=1;
for(int i=0;i<G
.size();i++)
{
int to=G
[i];
if(Depth[to]) continue;
Depth[to]=Depth
+1;
Father[to]=n;
dfs1(to);
SonAmount
+=SonAmount[to];
if(SonAmount[to]>SonAmount[Hson
]) Hson
=to;
}
return;
}
void dfs2(int n, int prev)
{
Dfsnum
=++dfscount;
TreeValue[dfscount]=Val
;
TopOfHeavyChain
=prev;
if(!Hson
) return;
dfs2(Hson
, prev);
for(int i=0;i<G
.size();i++)
{
int to=G
[i];
if(to==Hson
||to==Father
) continue;
dfs2(to, to);
}
}

struct Stree
{
int block;
int lcol, rcol;
int lazy;
Stree() { block=0;lcol=rcol=lazy=0; }
Stree operator + (const Stree &b)const
{
Stree res;
res.lcol=lcol, res.rcol=b.rcol;
if(rcol==b.lcol) res.block=block+b.block-1;
else res.block=block+b.block;

return res;
}
}stree[MAXN<<2];
void build(int l, int r, int rt)
{
if(l==r)
{
stree[rt].block=1;
stree[rt].lcol=stree[rt].rcol=TreeValue[l];
return;
}
int mid=(l+r)>>1;
build(lson), build(rson);
stree[rt]=stree[rt<<1]+stree[rt<<1|1];
}
void pushdown(int rt)
{
if(stree[rt].lazy!=0)
{
int c=stree[rt].lazy;stree[rt].lazy=0;
stree[rt<<1].lazy=stree[rt<<1|1].lazy=c;
stree[rt<<1].block=stree[rt<<1|1].block=1;
stree[rt<<1].lcol=stree[rt<<1|1].lcol=c;
stree[rt<<1].rcol=stree[rt<<1|1].rcol=c;
}
}
void update(int L, int R, int c, int l, int r, int rt)
{
if(L<=l&&r<=R)
{
stree[rt].block=1;
stree[rt].lazy=c;
stree[rt].lcol=stree[rt].rcol=c;
return;
}
pushdown(rt);
int mid=(l+r)>>1;
if(L<=mid) update(L, R, c, lson);
if(mid<R) update(L, R, c, rson);
stree[rt]=stree[rt<<1]+stree[rt<<1|1];
}
Stree query(int L, int R, int l, int r, int rt)
{
if(L<=l&&r<=R) return stree[rt];
pushdown(rt);
int mid=(l+r)>>1;
bool tl=0, tr=0;
if(R<=mid) return query(L, R, lson);
if(mid<L) return query(L, R, rson);
return query(L, R, lson)+query(L, R, rson);
}
void solvequ(int n)
{
Stree lc, rc;
int l, r;scanf("%d%d", &l, &r);
int fl=TopOfHeavyChain[l], fr=TopOfHeavyChain[r];
while(fl!=fr)
{
if(Depth[fl]>Depth[fr])
{
lc=query(Dfsnum[fl], Dfsnum[l], 1, n, 1)+lc;
l=Father[fl];
fl=TopOfHeavyChain[l];
}
else
{
rc=query(Dfsnum[fr], Dfsnum[r], 1, n, 1)+rc;
r=Father[fr];
fr=TopOfHeavyChain[r];
}
}
if(Depth[l]>Depth[r])
lc=query(Dfsnum[r], Dfsnum[l], 1, n, 1)+lc;
else rc=query(Dfsnum[l], Dfsnum[r], 1, n, 1)+rc;
swap(lc.lcol, lc.rcol);
printf("%d\n", (lc+rc).block);
}
void solveup(int n)
{
int l, r;scanf("%d%d", &l, &r);
int c;scanf("%d", &c);
int fl=TopOfHeavyChain[l], fr=TopOfHeavyChain[r];
while(fl!=fr)
{
if(Depth[fl]>Depth[fr])
{
update(Dfsnum[fl], Dfsnum[l], c, 1, n, 1);
l=Father[fl];
fl=TopOfHeavyChain[l];
}
else
{
update(Dfsnum[fr], Dfsnum[r], c, 1, n, 1);
r=Father[fr];
fr=TopOfHeavyChain[r];
}
}
if(Depth[l]>Depth[r])
update(Dfsnum[r], Dfsnum[l], c, 1, n, 1);
else update(Dfsnum[l], Dfsnum[r], c, 1, n, 1);
}
int main()
{
//freopen("in.txt", "r", stdin);
//freopen("ou1.txt", "w", stdout);
int n, m;
while(scanf("%d%d", &n, &m)==2)
{
dfscount=0;M(Hson, 0);
for(int i=1;i<=n;i++) G[i].clear();

for(int i=1;i<=n;i++) scanf("%d", &Val[i]);
for(int i=1;i<n;i++)
{
int ta, tb;scanf("%d%d", &ta, &tb);
AddEdge(ta, tb);
}

Depth[1]=1;dfs1(1);dfs2(1, 1);
build(1, n, 1);

while(m--)
{
char s[10];scanf("%s", s);
if(s[0]=='C') solveup(n);
else solvequ(n);
}
}
//system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: