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
",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
",p[i].ans);
198     }
199     return 0;
200 }
原文地址:https://www.cnblogs.com/blog-Dr-J/p/9589142.html