bzoj3307雨天的尾巴(权值线段树合并/DSU on tree)
题目大意:
一颗树,想要在树链上添加同一物品,问最后每个点上哪个物品最多。
解题思路:
1.线段树合并
假如说物品数量少到可以暴力添加,且树点极少,我们怎么做。
首先在一个树节点上标记出哪些物品有多少,寻找道路上的节点暴力添加。
而如果节点比较多,我们使用树上差分u+1,v+1,lca-1,fa[lca]-1向上求和就得到了答案
而颜色较多呢,和刚才唯一不同就在于向上求和时不要用数组,用线段树合并就好了(记录线段树区间的最大值与最大位置)
废点的回收是非常实用的^_^
时间复杂度O(nlogn)
代码:
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define lll tr[spc].ls 6 #define rrr tr[spc].rs 7 const int maxin=1000000000; 8 struct pnt{ 9 int fa[20]; 10 int hd; 11 int gd; 12 int dp; 13 int wgt; 14 int ans; 15 int prp; 16 int root; 17 }p[110000]; 18 struct ent{ 19 int twd; 20 int lst; 21 }e[220000]; 22 struct ljt{ 23 int twd; 24 int lst; 25 int vls; 26 }el[420000]; 27 struct trnt{ 28 int ls; 29 int rs; 30 int val; 31 int mpl; 32 }tr[2000000],org; 33 int bin[2000000]; 34 int top; 35 int siz; 36 int cnt1; 37 int cnt2; 38 int n,m; 39 void adde(int f,int t) 40 { 41 cnt1++; 42 e[cnt1].twd=t; 43 e[cnt1].lst=p[f].hd; 44 p[f].hd=cnt1; 45 return ; 46 } 47 void addc(int pt,int c,int v) 48 { 49 cnt2++; 50 el[cnt2].twd=c; 51 el[cnt2].lst=p[pt].gd; 52 el[cnt2].vls=v; 53 p[pt].gd=cnt2; 54 return ; 55 } 56 namespace Sgt{ 57 void P_delete(int spc) 58 { 59 bin[++top]=spc; 60 tr[spc]=org; 61 return ; 62 } 63 void P_destory(int spc1,int spc2) 64 { 65 P_delete(spc1); 66 P_delete(spc2); 67 return ; 68 } 69 int P_new(void) 70 { 71 if(top) 72 return bin[top--]; 73 return ++siz; 74 } 75 void pushup(int spc) 76 { 77 if(tr[lll].val>=tr[rrr].val) 78 tr[spc].val=tr[lll].val,tr[spc].mpl=tr[lll].mpl; 79 else 80 tr[spc].val=tr[rrr].val,tr[spc].mpl=tr[rrr].mpl; 81 return ; 82 } 83 int P_merge(int spc1,int spc2,int l,int r) 84 { 85 if(!spc1||!spc2) 86 return spc1+spc2; 87 int spc=P_new(); 88 if(l==r) 89 { 90 tr[spc].val=tr[spc1].val+tr[spc2].val; 91 tr[spc].mpl=l; 92 P_destory(spc1,spc2); 93 return spc; 94 } 95 int mid=(l+r)>>1; 96 tr[spc].ls=P_merge(tr[spc1].ls,tr[spc2].ls,l,mid); 97 tr[spc].rs=P_merge(tr[spc1].rs,tr[spc2].rs,mid+1,r); 98 pushup(spc); 99 P_destory(spc1,spc2); 100 return spc; 101 } 102 void Update(int l,int r,int &spc,int pos,int v) 103 { 104 if(!spc) 105 spc=P_new(); 106 if(l==r) 107 { 108 tr[spc].val+=v; 109 tr[spc].mpl=(tr[spc].val)?l:0; 110 return ; 111 } 112 int mid=(l+r)>>1; 113 if(pos<=mid) 114 Update(l,mid,tr[spc].ls,pos,v); 115 else 116 Update(mid+1,r,tr[spc].rs,pos,v); 117 pushup(spc); 118 if(!tr[spc].val) 119 tr[spc].mpl=0; 120 return ; 121 } 122 } 123 void Basic_dfs(int x,int f) 124 { 125 p[x].dp=p[f].dp+1; 126 p[x].fa[0]=f; 127 for(int i=1;i<=19;i++) 128 p[x].fa[i]=p[p[x].fa[i-1]].fa[i-1]; 129 p[x].wgt=1; 130 for(int i=p[x].hd;i;i=e[i].lst) 131 { 132 int to=e[i].twd; 133 if(to==f) 134 continue; 135 Basic_dfs(to,x); 136 p[x].wgt+=p[to].wgt; 137 } 138 return ; 139 } 140 void Ans_dfs(int x,int f) 141 { 142 for(int i=p[x].hd;i;i=e[i].lst) 143 { 144 int to=e[i].twd; 145 if(to==f) 146 continue; 147 Ans_dfs(to,x); 148 } 149 for(int i=p[x].gd;i;i=el[i].lst) 150 { 151 int clr=el[i].twd; 152 Sgt::Update(1,maxin,p[x].root,clr,el[i].vls); 153 } 154 p[x].ans=tr[p[x].root].mpl; 155 p[f].root=Sgt::P_merge(p[f].root,p[x].root,1,maxin); 156 } 157 int Lca(int x,int y) 158 { 159 if(p[x].dp<p[y].dp) 160 std::swap(x,y); 161 for(int i=19;i>=0;i--) 162 if(p[p[x].fa[i]].dp>=p[y].dp) 163 x=p[x].fa[i]; 164 if(x==y) 165 return x; 166 for(int i=19;i>=0;i--) 167 if(p[x].fa[i]!=p[y].fa[i]) 168 x=p[x].fa[i],y=p[y].fa[i]; 169 return p[x].fa[0]; 170 } 171 int main() 172 { 173 scanf("%d%d",&n,&m); 174 for(int i=1;i<n;i++) 175 { 176 int a,b; 177 scanf("%d%d",&a,&b); 178 adde(a,b); 179 adde(b,a); 180 } 181 Basic_dfs(1,1); 182 for(int i=1;i<=m;i++) 183 { 184 int x,y,z; 185 scanf("%d%d%d",&x,&y,&z); 186 addc(x,z,1); 187 addc(y,z,1); 188 int lca=Lca(x,y); 189 addc(lca,z,-1); 190 if(lca!=1) 191 addc(p[lca].fa[0],z,-1); 192 } 193 Ans_dfs(1,1); 194 for(int i=1;i<=n;i++) 195 printf("%d\n",p[i].ans); 196 return 0; 197 }
2.DSU on tree
如同经典的DSU on tree,重链剖分,对轻儿子暴力修改,只不过使用权值线段树而不是桶,时间复杂度O(nlog2n),慢了点常数也大,但数据105还是没有问题的
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define lll spc<<1 5 #define rrr spc<<1|1 6 const int maxc=100000; 7 struct pnt{ 8 int hd; 9 int gd; 10 int fa; 11 int tp; 12 int dp; 13 int wgt; 14 int mxs; 15 int ans; 16 }p[1000000]; 17 struct ent{ 18 int twd; 19 int lst; 20 }e[1000000]; 21 struct clr{ 22 int twd; 23 int lst; 24 int vls; 25 }c[1000000]; 26 struct trnt{ 27 int val; 28 int maxp; 29 }tr[10000000],stdtr; 30 int n,m; 31 int cnt; 32 int clt; 33 void ade(int f,int t) 34 { 35 cnt++; 36 e[cnt].twd=t; 37 e[cnt].lst=p[f].hd; 38 p[f].hd=cnt; 39 } 40 void adc(int f,int t,int v) 41 { 42 clt++; 43 c[clt].twd=t; 44 c[clt].lst=p[f].gd; 45 c[clt].vls=v; 46 p[f].gd=clt; 47 } 48 void pushup(int spc) 49 { 50 if(tr[lll].val>=tr[rrr].val) 51 tr[spc]=tr[lll]; 52 else 53 tr[spc]=tr[rrr]; 54 } 55 void update(int l,int r,int spc,int pos,int v) 56 { 57 if(l==r) 58 { 59 tr[spc].val+=v; 60 tr[spc].maxp=pos; 61 if(!tr[spc].val) 62 tr[spc].maxp=0; 63 return ; 64 } 65 int mid=(l+r)>>1; 66 if(pos<=mid) 67 update(l,mid,lll,pos,v); 68 else 69 update(mid+1,r,rrr,pos,v); 70 pushup(spc); 71 return ; 72 } 73 void Destroy(int l,int r,int spc) 74 { 75 tr[spc]=stdtr; 76 if(l==r) 77 return ; 78 int mid=(l+r)>>1; 79 Destroy(l,mid,lll); 80 Destroy(mid+1,r,rrr); 81 return ; 82 } 83 int Lca(int x,int y) 84 { 85 while(p[x].tp!=p[y].tp) 86 { 87 if(p[p[x].tp].dp<p[p[y].tp].dp) 88 std::swap(x,y); 89 x=p[p[x].tp].fa; 90 } 91 if(p[x].dp>p[y].dp) 92 std::swap(x,y); 93 return x; 94 } 95 void Basic_dfs(int x,int f) 96 { 97 int maxs=-1; 98 p[x].wgt=1; 99 p[x].dp=p[f].dp+1; 100 p[x].fa=f; 101 for(int i=p[x].hd;i;i=e[i].lst) 102 { 103 int to=e[i].twd; 104 if(to==f) 105 continue; 106 Basic_dfs(to,x); 107 p[x].wgt+=p[to].wgt; 108 if(p[to].wgt>maxs) 109 { 110 maxs=p[to].wgt; 111 p[x].mxs=to; 112 } 113 } 114 return ; 115 } 116 void Sec_dfs(int x,int f,int top) 117 { 118 if(!x) 119 return ; 120 p[x].tp=top; 121 Sec_dfs(p[x].mxs,x,top); 122 for(int i=p[x].hd;i;i=e[i].lst) 123 { 124 int to=e[i].twd; 125 if(!p[to].tp) 126 Sec_dfs(to,x,to); 127 } 128 129 } 130 void Add_dfs(int x,int f) 131 { 132 for(int i=p[x].gd;i;i=c[i].lst) 133 update(1,maxc,1,c[i].twd,c[i].vls); 134 for(int i=p[x].hd;i;i=e[i].lst) 135 if(e[i].twd!=f) 136 Add_dfs(e[i].twd,x); 137 } 138 void Des_dfs(int x,int f) 139 { 140 for(int i=p[x].gd;i;i=c[i].lst) 141 update(1,maxc,1,c[i].twd,-c[i].vls); 142 for(int i=p[x].hd;i;i=e[i].lst) 143 if(e[i].twd!=f) 144 Des_dfs(e[i].twd,x); 145 } 146 void DSU_dfs(int x,int f,bool hv) 147 { 148 if(!x) 149 return ; 150 for(int i=p[x].hd;i;i=e[i].lst) 151 { 152 int to=e[i].twd; 153 if(to==f||to==p[x].mxs) 154 continue; 155 DSU_dfs(to,x,false); 156 } 157 DSU_dfs(p[x].mxs,x,true); 158 for(int i=p[x].hd;i;i=e[i].lst) 159 { 160 int to=e[i].twd; 161 if(to==f||to==p[x].mxs) 162 continue; 163 Add_dfs(to,x); 164 } 165 for(int i=p[x].gd;i;i=c[i].lst) 166 update(1,maxc,1,c[i].twd,c[i].vls); 167 p[x].ans=tr[1].maxp; 168 if(!hv) 169 Des_dfs(x,f); 170 } 171 int main() 172 { 173 scanf("%d%d",&n,&m); 174 for(int i=1;i<n;i++) 175 { 176 int a,b; 177 scanf("%d%d",&a,&b); 178 ade(a,b); 179 ade(b,a); 180 } 181 Basic_dfs(1,1); 182 Sec_dfs(1,1,1); 183 for(int i=1;i<=m;i++) 184 { 185 int x,y,z; 186 scanf("%d%d%d",&x,&y,&z); 187 int l=Lca(x,y); 188 adc(x,z,1); 189 adc(y,z,1); 190 adc(l,z,-1); 191 if(l!=1) 192 adc(p[l].fa,z,-1); 193 } 194 DSU_dfs(1,1,1); 195 for(int i=1;i<=n;i++) 196 { 197 printf("%d\n",p[i].ans); 198 } 199 return 0; 200 }