标签:
题解摘要:树链剖分后用线段树区间查询修改,对于安装软件,将改点到根的路径全部变为1,对于卸载软件,将子树清空。注意边界,编号是从0开始的,容易漏掉树根。
第一次写树剖~
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #include <ctime> 8 9 using namespace std; 10 11 struct Edge 12 { 13 int to,next; 14 }e[210000]; 15 16 int ind,n,Pre[210000],f[810000],Sum[810000],Out_dfn[210000]; 17 int p[210000],cnt,hv[210000],Head[210000],Dfn[210000]; 18 19 void Add_edge(const int & x,const int & y) 20 { 21 e[++cnt].to=y; 22 e[cnt].next=p[x]; 23 p[x]=cnt; 24 return ; 25 } 26 27 int Init_Dfs(const int& S) 28 { 29 int num=1,i,Max_=0; 30 for(i=p[S];i;i=e[i].next) 31 { 32 int temp=Init_Dfs(e[i].to); 33 if(temp>Max_)Max_=temp,hv[S]=e[i].to; 34 num+=temp; 35 } 36 return num; 37 } 38 39 void Dfs(const int& S,const int& fa) 40 { 41 int i; 42 if(!Head[S])Head[S]=Head[fa];Dfn[S]=++ind; 43 44 if(hv[S])Dfs(hv[S],S); 45 for(i=p[S];i;i=e[i].next) 46 { 47 if(e[i].to!=hv[S]) 48 { 49 Head[e[i].to]=e[i].to; 50 Pre[e[i].to]=S; 51 Dfs(e[i].to,S); 52 } 53 } 54 Out_dfn[S]=ind; 55 return ; 56 } 57 58 inline void push_down(const int & num,const int & l,const int & r) 59 { 60 if(f[num]) 61 { 62 if(l!=r) 63 { 64 f[num<<1]=f[num<<1|1]=f[num]; 65 } 66 if(f[num]==1)Sum[num]=r-l+1; 67 if(f[num]==-1)Sum[num]=0; 68 f[num]=0; 69 } 70 return ; 71 } 72 73 void push_up(const int & num,const int & l,const int & r) 74 { 75 if(l!=r) 76 { 77 int mid=l+((r-l)>>1); 78 push_down(num<<1,l,mid); 79 push_down(num<<1|1,mid+1,r); 80 Sum[num]=Sum[num<<1]+Sum[num<<1|1]; 81 } 82 return ; 83 } 84 85 void Change(const int & l,const int & r,const int & num, 86 const int & s,const int & t,const int &d) 87 { 88 if(s<=l && r<=t) 89 { 90 f[num]=d; 91 push_down(num,l,r); 92 return ; 93 } 94 int mid=l+((r-l)>>1); 95 push_down(num,l,r); 96 if(s<=mid)Change(l,mid,num<<1,s,t,d); 97 if(t>mid) Change(mid+1,r,num<<1|1,s,t,d); 98 push_up(num,l,r); 99 return ; 100 } 101 102 int Query(const int & l,const int & r,const int & num, 103 const int & s,const int & t) 104 { 105 if(s<=l && r<=t) 106 { 107 push_down(num,l,r); 108 return Sum[num]; 109 } 110 111 int mid=l+((r-l)>>1),temp=0; 112 push_down(num,l,r); 113 if(s<=mid)temp+=Query(l,mid,num<<1,s,t); 114 if(t>mid) temp+=Query(mid+1,r,num<<1|1,s,t); 115 push_up(num,l,r); 116 return temp; 117 } 118 119 int Get_sum_install(const int& S) 120 { 121 int x=S,temp=0,sum=0; 122 123 while(x) 124 { 125 sum+=Query(1,n,1,Dfn[Head[x]],Dfn[x]); 126 Change(1,n,1,Dfn[Head[x]],Dfn[x],1); 127 temp+=Dfn[x]-Dfn[Head[x]]+1; 128 x=Pre[Head[x]]; 129 } 130 131 return temp-sum; 132 } 133 134 int Get_sum_remove(const int & S) 135 { 136 int x=S,sum=0; 137 138 sum=Query(1,n,1,Dfn[x],Out_dfn[x]); 139 Change(1,n,1,Dfn[x],Out_dfn[x],-1); 140 141 return sum; 142 } 143 144 int main() 145 { 146 147 int i,x,q; 148 char op[15]; 149 150 scanf("%d",&n); 151 for(i=2;i<=n;++i) 152 { 153 scanf("%d",&x);x++; 154 Add_edge(x,i); 155 } 156 157 Init_Dfs(1); 158 159 Head[1]=1; 160 Dfs(1,1); 161 scanf("%d",&q); 162 for(i=1;i<=q;++i) 163 { 164 scanf("%s%d",op,&x);x++; 165 if(op[0]==‘i‘) 166 printf("%d\n",Get_sum_install(x)); 167 else 168 printf("%d\n",Get_sum_remove(x)); 169 } 170 171 return 0; 172 }
不知道为什么,BZOJ TLE了,但是UOJ AC(求大神指教)??
[Bzoj4196] [NOI2015] 软件包管理器 [树链剖分,线段树]
标签:
原文地址:http://www.cnblogs.com/Gster/p/4977886.html