bzoj 2243 染色
来源:互联网 发布:五五开和笑笑 知乎 编辑:程序博客网 时间:2024/06/12 01:29
一个比较裸的树剖题
先考虑区间处理的情况,我们维护区间颜色段数,区间左右端点的颜色之后这就可以满足区间合并了
然后用树剖的方法处理一下就好
ps:用结构体保存区间值重载加号表示区间合并不能更方便
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;const int maxn = 312345;struct Info{ int l,r; int siz; void init(int x){ l = r = x; siz = 1; } void clear(){ l = r = siz = -1; } Info(){} Info(int l,int r,int siz):l(l),r(r),siz(siz){}};Info rev(Info v){ return Info(v.r,v.l,v.siz);}Info operator + (Info l,Info r){ if(l.siz == -1) return r; if(r.siz == -1) return l; Info ret(l.l,r.r,l.siz+r.siz); if(l.r == r.l) ret.siz--; return ret;}Info info[maxn*4];int lazy[maxn*4];#define root 1,1,n#define Now int o,int l,int r#define Mid int m = l + (r - l)/2#define lson o<<1,l,m#define rson o<<1|1,m+1,rvoid push_down(Now){ int v = lazy[o]; lazy[o] = -1; if(l != r){ info[o<<1].init(v); info[o<<1|1].init(v); lazy[o<<1] = lazy[o<<1|1] = v; }}void update(Now,int ul,int ur,int v){ if(ul <= l && r <= ur){ lazy[o] = v; info[o].init(v); return; } Mid; if(lazy[o] != -1)push_down(o,l,r); if(ul <= m) update(lson,ul,ur,v); if(m+1 <= ur) update(rson,ul,ur,v); info[o] = info[o<<1] + info[o<<1|1];}Info query(Now,int ql,int qr){ if(ql <= l && r <= qr) return info[o]; Mid; if(lazy[o] != -1) push_down(o,l,r); Info ret; ret.clear(); if(ql <= m) ret = query(lson,ql,qr) + ret; if(m+1 <= qr) ret = ret + query(rson,ql,qr); return ret;}void sinit(){ memset(lazy,-1,sizeof(lazy));}//---treesplitevector<int> edge[maxn];void Link(int st,int ed){ edge[st].push_back(ed); edge[ed].push_back(st);}void init(int n){ for(int i=0;i<=n;i++){ edge[i].clear(); }}int fa[maxn],son[maxn],siz[maxn];int deep[maxn],top[maxn],tid[maxn];int _cnt;void dffs(int st,int Fa,int Deep){ son[st] = -1,fa[st] = Fa; deep[st] = Deep,siz[st] = 1; for(vector<int>::iterator it = edge[st].begin();it!=edge[st].end();it++){ int x = *it; if( x != Fa){ dffs(x,st,Deep+1); siz[st] += siz[x]; if(son[st] == -1 || siz[son[st]] < siz[x]) son[st] = x; } }}void dfss(int st,int Top){ tid[st] = _cnt ++; top[st] = Top; if(son[st] != -1){ dfss(son[st],Top); } for(vector<int>::iterator it = edge[st].begin();it!=edge[st].end();it++){ int x = *it; if(x != fa[st] && x != son[st]){ dfss(x,x); } }}void splite(){ _cnt = 1; dffs(1,-1,1); dfss(1,1);}int n;void UPD(int x,int y,int v){ int tx,ty; tx = top[x],ty = top[y]; while(tx != ty){ if(deep[tx] < deep[ty]){ swap(x,y),swap(tx,ty); } update(root,tid[tx],tid[x],v); x = fa[tx],tx = top[x]; } if(deep[x] < deep[y]) swap(x,y); update(root,tid[y],tid[x],v);}Info QUE(int x,int y){ Info X,Y; X.clear(); Y.clear(); int tx,ty; tx = top[x],ty = top[y]; while(tx != ty){ if(deep[tx] < deep[ty]) swap(x,y),swap(X,Y),swap(tx,ty); X = query(root,tid[tx],tid[x]) + X; x = fa[tx],tx = top[x]; } if(deep[x] < deep[y]) swap(x,y),swap(X,Y); return rev(X) + rev(query(root,tid[y],tid[x])) + Y;}int arr[maxn];int main(){ int m; while(~scanf("%d %d",&n,&m)){ for(int i=1;i<=n;i++){ scanf("%d",&arr[i]); } init(n); int x,y; for(int i=1;i<n;i++){ scanf("%d %d",&x,&y); Link(x,y); } splite(); sinit(); for(int i=1;i<=n;i++){ update(root,tid[i],tid[i],arr[i]); } int v; char ord[3]; while(m--){ scanf("%s",ord); scanf("%d %d",&x,&y); if(*ord == 'Q'){ printf("%d\n",QUE(x,y).siz); } else{ scanf("%d",&v); UPD(x,y,v); } } } return 0;}
初始化的时候把lazy memset成0的丝薄应该只有我
还有树剖查询的时候忘记加上原来的区间直接赋值的也是没谁了。。。
0 0
- 【BZOJ - 2243】 SDOI2011 染色
- BZOJ 2243: [SDOI2011]染色
- BZOJ 2243 染色 树链剖分
- 【BZOJ 2243】 [SDOI2011]染色
- bzoj 2243: [SDOI2011]染色
- bzoj 2243 染色(树链剖分)
- [BZOJ 2243] 染色
- bzoj 2243 树链剖分 染色
- bzoj-2243 染色
- 【BZOJ】2243 染色
- BZOJ 2243 染色 树链剖分
- BZOJ 2243 染色 [树链剖分]
- bzoj 2243 染色
- 【BZOJ 2243】染色 【树链剖分】
- bzoj 2243: [SDOI2011]染色
- 【BZOJ 2243】[SDOI2011]染色
- BZOJ 2243, 染色
- BZOJ 2243 [SDOI2011] 染色
- C++基础之宏的使用
- 二叉树几种遍历算法的非递归实现
- C++设计模式浅识单例模式
- ListView滑动删除效果实现
- nginx的配置文件详细说明
- bzoj 2243 染色
- 安卓入门--Activity跳转页面
- I2C总线协议
- jeesite图片路径去掉“|” 只能上传单个图片
- vim粘贴复制学习
- Codeforces Gym 100971M Decomposition into Good Strings DP+数据结构
- Dungeon Master POJ 2251
- [GDOI2016]机密网络
- 函数模板 类模板