NOI2015软件包管理器
Posted cdcq(本博客废弃!现用博客:https://www.cn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOI2015软件包管理器相关的知识,希望对你有一定的参考价值。
NOI难得的水题,话说还是T2诶……又学到了线段树的一种新的魔性使用
看sxysxy大神的代码才写出来的,sxysxy_orz
原题:
Linux用户和OSX用户一定对软件包管理器不会陌生。通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置。Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器。
主要就是两种树上线段树,树剖和dfs序列化,很裸,不过这里有一种线段树的魔性使用:(2017.12.5 upd:其实这就是个常规的赋值应用,我当年真是naive23333
给线段树修改的时候,delta不是+=z,而是=z,这个表示吧一个区间里面所有的数都变成z,一般用区间里面的数为1或0来表示有没有
然后在计算value(这里表示一个区间里面有几个)的时候应该是tree[x].delta*(tree[x].sright-tree[x].sleft+1);表示这一段区间里的东西要么有(delta=1),要么没有(delta=0),乘上长度就是有的个数
添加的时候先查一下这个点上面有几个,然后buff一下,用buff的长度减去之前查找的个数,就是需要再添加的个数
然后就是两种树上线段树结合一下很开心的水过了,因为树链的一端只能是根节点,所以在爬链的时候比原版本还要简单
不过写的时候犯了一个非常傻逼的错误,调了几十分钟
x=father[top[x]]写成x=father[x],整整多了几条链的复杂度qaqqqqqqqqqqqqqqqq
还以为是卡常问题,找了好长时间……
说一下几点需要注意的地方:
0是有意义的,所以如果没有重儿子要设成-1
同样因为标号从0开始,所以总共有7个点,但是标号只到6,dfs序的计数器初始化要设成-1(从0开始)
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 int read(){int z=0,mark=1; char ch=getchar(); 8 while(ch<\'0\'||ch>\'9\'){if(ch==\'-\')mark=-1; ch=getchar();} 9 while(ch>=\'0\'&&ch<=\'9\'){z=(z<<3)+(z<<1)+ch-\'0\'; ch=getchar();} 10 return z*mark; 11 } 12 struct ddd{int next,y;}e[110000];int LINK[110000],ltop=0; 13 inline void insert(int x,int y){e[++ltop].next=LINK[x];LINK[x]=ltop;e[ltop].y=y;} 14 int n,m; 15 int size[110000],deep[110000],father[110000],big_child[110000],top[110000],n_value[110000]; 16 int dfs_xv[110000],fan_xv[110000],er_xv[110000],xv_cnt=-1;//注意因为从0开始,所以总共有7个点,但是编号只到6 17 void dfs1(int x,int _father,int _deep){ 18 father[x]=_father,deep[x]=_deep,size[x]=1; 19 int max_size=0,max_child=-1;//注意0有意义 20 for(int i=LINK[x];i;i=e[i].next)if(e[i].y!=father[x]){ 21 dfs1(e[i].y,x,_deep+1); 22 size[x]+=size[e[i].y]; 23 if(size[e[i].y]>max_size) max_size=size[e[i].y],max_child=e[i].y; 24 } 25 big_child[x]=max_child; 26 } 27 void dfs2(int x,int _top){ 28 top[x]=_top; dfs_xv[++xv_cnt]=x; fan_xv[x]=xv_cnt; 29 if(big_child[x]!=-1) dfs2(big_child[x],_top);//注意-1 30 for(int i=LINK[x];i;i=e[i].next)if(e[i].y!=father[x] && e[i].y!=big_child[x]) 31 dfs2(e[i].y,e[i].y); 32 er_xv[x]=xv_cnt; 33 } 34 struct dcd{int sleft,sright,mid,svalue,delta;}tree[5100000]; 35 void stev(int x){ tree[x].svalue=tree[x].delta*(tree[x].sright-tree[x].sleft+1);}//sxysxy_orz 36 void get_SegmentTree(int x,int _left,int _right){ 37 tree[x].sleft=_left,tree[x].sright=_right,tree[x].mid=(_left+_right)>>1; 38 tree[x].svalue=tree[x].delta=0; 39 if(_left!=_right) get_SegmentTree(x<<1,_left,tree[x].mid),get_SegmentTree(x<<1|1,tree[x].mid+1,_right); 40 } 41 int search(int x,int _left,int _right){ 42 if(tree[x].sleft==_left && tree[x].sright==_right) return tree[x].svalue; 43 else{ 44 if(tree[x].delta!=-1){ 45 tree[x<<1].delta=tree[x<<1|1].delta=tree[x].delta; tree[x].delta=-1;//注意这里并不是加上,而是设置为,注意-1 (sxysxy_orz 46 stev(x<<1),stev(x<<1|1); 47 tree[x].delta=-1; 48 } 49 if(_left<=tree[x].mid && _right>tree[x].mid) return search(x<<1,_left,tree[x].mid)+search(x<<1|1,tree[x].mid+1,_right); 50 else if(_right<=tree[x].mid) return search(x<<1,_left,_right); 51 else return search(x<<1|1,_left,_right); 52 } 53 } 54 void buff(int x,int _left,int _right,int z){ 55 if(tree[x].sleft==_left && tree[x].sright==_right) tree[x].delta=z,stev(x); 56 else{ 57 if(tree[x].delta!=-1){ 58 tree[x<<1].delta=tree[x<<1|1].delta=tree[x].delta; tree[x].delta=-1; 59 stev(x<<1),stev(x<<1|1); 60 tree[x].delta=-1; 61 } 62 if(_left<=tree[x].mid && _right>tree[x].mid) buff(x<<1,_left,tree[x].mid,z),buff(x<<1|1,tree[x].mid+1,_right,z); 63 else if(_right<=tree[x].mid) buff(x<<1,_left,_right,z); 64 else buff(x<<1|1,_left,_right,z); 65 tree[x].svalue=tree[x<<1].svalue+tree[x<<1|1].svalue; 66 } 67 } 68 int install(int x){ 69 int ans=0; 70 while(x!=-1){ 71 ans+=fan_xv[x]-fan_xv[top[x]]+1-search(1,fan_xv[top[x]],fan_xv[x]); 72 buff(1,fan_xv[top[x]],fan_xv[x],1); 73 //x=father[x] 我是傻逼qaqqqqqqqqqqqqqqqqqqqq 74 x=father[top[x]]; 75 } 76 return ans; 77 } 78 int uninstall(int x){ 79 int ans=search(1,fan_xv[x],er_xv[x]); 80 buff(1,fan_xv[x],er_xv[x],0); 81 return ans; 82 } 83 int main(){ 84 /*freopen("ddd.in","r",stdin); 85 freopen("ddd.out","w",stdout);*/ 86 freopen("manager.in","r",stdin); 87 freopen("manager.out","w",stdout); 88 cin>>n; 89 for(int i=1;i<n;i++) insert(read(),i),n_value[i]=0; 90 dfs1(0,-1,1),dfs2(0,0),get_SegmentTree(1,0,n-1); 91 cin>>m; 92 char ch; int _id; 93 while(m --> 0){//趋向于 94 ch=getchar(); 95 while(ch!=\'i\' && ch!=\'u\') ch=getchar(); 96 if(ch==\'i\'){ 97 for(int i=1;i<=6;i++) ch=getchar(); 98 _id=read(); 99 printf("%d\\n",install(_id)); 100 } 101 else{ 102 for(int i=1;i<=8;i++) ch=getchar(); 103 _id=read(); 104 printf("%d\\n",uninstall(_id)); 105 } 106 } 107 return 0; 108 }
以上是关于NOI2015软件包管理器的主要内容,如果未能解决你的问题,请参考以下文章
bzoj4196 [Noi2015]软件包管理器——树链剖分
Bzoj 4196: [Noi2015]软件包管理器 树链剖分