链剖——BZOJ4196/Luogu2146 [Noi2015]软件包管理器
来源:互联网 发布:java游戏吧 编辑:程序博客网 时间:2024/06/05 05:40
题面:BZOJ4196 Luogu2146
首先软件包形成了一棵树,然后题中的软件包只有两种状态:装了与没被装
如果要装某个软件包,那么从这个包到根的软件包都要装
如果要卸某个软件包,那么以这个软件包为根的子树软件包都不能装
所以这道题实际要我们干什么:树上修改一条链的值,修改子树的值,求一条链的和,求子树和
然后发现要求的操作和洛谷的树剖模板题几乎一样?!
那么就把Luogu的模板拿来改一下就好了(逃
(不过那是不可能的)两题题面还是有很大的不同的
这道NOI原题要求边询问边修改,这个倒不是难题,直接跟在询问后面好了
关于子树相关操作其实也很简单,dfs序之后节点x的整棵子树区间范围连续且确定在sx[x]~sx[x]+s[x]-1(sx[x]为x转到线段树里的编号,s[x]表示以x为根子树大小)
关键在于树剖之后的线段树处理的细节部分。。。(我卡了很久吧。。。)
我是把软件包的状态看成0/1,0表示装了1表示没装(这样有利于链上操作而且子树操作也不受太大影响)
然后查的时候把1搞出来,边查边改,计算答案,细节很多
#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<iostream>#include<cstdlib>#include<string>#include<ctime>#include<queue>#include<climits>using namespace std;char c[11];int n,nedge=0,p[200001],nex[200001],head[200001];int fa[100001],deep[100001],s[100001],son[100001],top[100001];int sx[100001],xs[100001],ne=0;int lt[400001],rt[400001],t[400001],add[400001];inline void addedge(int a,int b){p[++nedge]=b;nex[nedge]=head[a];head[a]=nedge;}inline void dfs(int x,int Fa,int dep){ fa[x]=Fa;deep[x]=dep;s[x]=1; for(int k=head[x];k;k=nex[k]){ if(p[k]==Fa)continue; dfs(p[k],x,dep+1);s[x]+=s[p[k]]; if(!son[x]||s[p[k]]>s[son[x]])son[x]=p[k]; }}inline void dfss(int x,int bh){ top[x]=bh;sx[x]=++ne;xs[sx[x]]=x; if(!son[x])return; dfss(son[x],bh); for(int k=head[x];k;k=nex[k])if(p[k]!=son[x]&&p[k]!=fa[x])dfss(p[k],p[k]);}inline void clean(int nod){//lazy标记下传 if(add[nod]==-1)return; if(lt[nod]!=rt[nod]){ t[nod*2]=add[nod]*(rt[nod*2]-lt[nod*2]+1); add[nod*2]=add[nod]; t[nod*2+1]=add[nod]*(rt[nod*2+1]-lt[nod*2+1]+1); add[nod*2+1]=add[nod]; } add[nod]=-1;}inline void build(int l,int r,int nod){ lt[nod]=l;rt[nod]=r; if(l==r){t[nod]=add[nod]=1;return;} int mid=l+r>>1; build(l,mid,nod*2);build(mid+1,r,nod*2+1); t[nod]=t[nod*2]+t[nod*2+1];add[nod]=1;}inline void xg(int i,int j,int nod,int w){ clean(nod); if(lt[nod]>=i&&rt[nod]<=j){t[nod]=(rt[nod]-lt[nod]+1)*w;add[nod]=w;return;} int mid=lt[nod]+rt[nod]>>1; if(i<=mid)xg(i,j,nod*2,w); if(j>mid)xg(i,j,nod*2+1,w); t[nod]=t[nod*2]+t[nod*2+1];}inline int ssum(int i,int j,int nod){ clean(nod); if(lt[nod]>=i&&rt[nod]<=j)return t[nod]; int mid=lt[nod]+rt[nod]>>1,ans=0; if(i<=mid)ans+=ssum(i,j,nod*2); if(j>mid)ans+=ssum(i,j,nod*2+1); return ans;}inline int fsum(int x,int y){ int fx=top[x],fy=top[y],ans=0; while(fx!=fy){ if(deep[fx]<deep[fy])swap(fx,fy),swap(x,y); ans+=ssum(sx[fx],sx[x],1);xg(sx[fx],sx[x],1,0);//边查边改1 x=fa[fx];fx=top[x]; } if(deep[x]>deep[y])swap(x,y); ans+=ssum(sx[x],sx[y],1);xg(sx[x],sx[y],1,0);//边查边改2 return ans;}int main(){ scanf("%d",&n); for(int i=1;i<n;i++){ int x;scanf("%d",&x); addedge(x,i);addedge(i,x); } dfs(0,-1,1);dfss(0,0);build(1,n,1); int m;scanf("%d",&m); for(int i=1;i<=m;i++){ int x;scanf("%s%d",c+1,&x); if(c[1]=='i')printf("%d\n",fsum(0,x)); else{ printf("%d\n",s[x]-ssum(sx[x],sx[x]+s[x]-1,1)); xg(sx[x],sx[x]+s[x]-1,1,1);//处理子树部分 } } return 0;}
阅读全文
1 0
- 链剖——BZOJ4196/Luogu2146 [Noi2015]软件包管理器
- BZOJ4196——noi2015软件包管理器
- bzoj4196: [Noi2015]软件包管理器
- 【NOI2015】【BZOJ4196】软件包管理器
- [BZOJ4196][Noi2015]软件包管理器
- bzoj4196[Noi2015]软件包管理器
- bzoj4196【NOI2015】软件包管理器
- bzoj4196软件包管理器 noi2015
- [BZOJ4196] [Noi2015]软件包管理器
- 【NOI2015】BZOJ4196软件包管理器
- bzoj4196[NOI2015]软件包管理器
- bzoj4196: [NOI2015]软件包管理器
- bzoj4196: [Noi2015]软件包管理器
- bzoj4196: [Noi2015]软件包管理器
- bzoj4196: [Noi2015]软件包管理器
- BZOJ4196: [Noi2015]软件包管理器
- 【bzoj4196】[NOI2015]软件包管理器
- bzoj4196 [Noi2015]软件包管理器
- SCI论文投稿中图、表和公式的位置问题
- ONVIF协议网络摄像机(IPC)客户端程序开发(3):理解什么是Web Services
- POJ2456-Aggressive cows
- 使得ul标签中的li水平排列
- 基于支持向量机(SVM)的遗传疾病致病位点预测分析
- 链剖——BZOJ4196/Luogu2146 [Noi2015]软件包管理器
- Struts1框架一之项目的配置及执行流程
- ios开发之NSBundle
- 关于数据库主键和外键(终于弄懂啦)
- Discuz!教程之如何修改附件下载次数
- Linux命令基础29-head和tail命令
- java读取openssl的pkcs8格式的aes128加密的私钥文件
- 【项目管理】需求-用户故事Invest原则
- 5.17 JLL实习日志-实现get方式过滤数据,表格形式展现在前端