1. 程式人生 > >樹剖+線段樹||樹鏈剖分||BZOJ1984||Luogu4315||月下“毛景樹”

樹剖+線段樹||樹鏈剖分||BZOJ1984||Luogu4315||月下“毛景樹”

題面:月下“毛景樹”

題解:是道很裸的樹剖,但處理的細節有點多(其實是自己線段樹沒學好)。用一個Dfs把邊權下移到點權,用E陣列記錄哪些邊被用到了;前三個更新的操作都可以合併起來,可以發現a到b節點間的邊權max實質是a節點到b節點的路徑中a下移一位後到b節點的點權max,意味著:若dep[a]<dep[b](若不是這樣可交換),找點權max上跳時不能到LCA(a,b);因為重邊會是連續的,所以直接(seg記錄節點線上段樹中的下標)seg[a]+1到seg[b]就可以了。然後要注意flag1和flag2的維護順序以及相互的影響。

_(:3J∠)_語文太差了,不好意思

  1 #include<cstdio>
  2
#include<cstring> 3 #include<iostream> 4 #define max(a,b) ((a)>(b)?(a):(b)) 5 using namespace std; 6 const int maxn=100005,maxm=100005; 7 int N,W[maxn],num_edge=0,edge_head[maxn],a,b,c,seg[maxn],rev[maxn],fa[maxn],top[maxn],son[maxn],size[maxn]; 8 int dep[maxn],Ans; 9 bool E[maxm<<1
]; 10 char o[20]; 11 inline int rd(){ 12 int x=0,f=1;char c=getchar(); 13 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 14 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 15 return f*x; 16 } 17 struct Edge{ 18 int from,to,nx,dis; 19 }edge[maxm<<1];
20 inline void Add_edge(int from,int to,int dis){ 21 edge[++num_edge].nx=edge_head[from]; 22 edge[num_edge].from=from; 23 edge[num_edge].to=to; 24 edge[num_edge].dis=dis; 25 edge_head[from]=num_edge; 26 return; 27 } 28 inline void Dfs(int x,int f){ 29 for(int i=edge_head[x];i;i=edge[i].nx){ 30 int y=edge[i].to; 31 if(y!=f){ 32 W[y]=edge[i].dis; 33 E[i]=1; 34 Dfs(y,x); 35 } 36 } 37 return; 38 } 39 inline void Dfs1(int x,int f){ 40 size[x]=1; 41 dep[x]=dep[f]+1; 42 fa[x]=f; 43 for(int i=edge_head[x];i;i=edge[i].nx){ 44 int y=edge[i].to; 45 if(y!=f){ 46 Dfs1(y,x); 47 size[x]+=size[y]; 48 if(size[y]>size[son[x]])son[x]=y; 49 } 50 } 51 return; 52 } 53 inline void Dfs2(int x){ 54 if(son[x]){ 55 int y=son[x]; 56 seg[y]=++seg[0]; 57 rev[seg[0]]=y; 58 top[y]=top[x]; 59 Dfs2(y); 60 } 61 for(int i=edge_head[x];i;i=edge[i].nx){ 62 int y=edge[i].to; 63 if(top[y]==0){ 64 seg[y]=++seg[0]; 65 rev[seg[0]]=y; 66 top[y]=y; 67 Dfs2(y); 68 } 69 } 70 return; 71 } 72 struct Tree{ 73 int l,r,maxs,flag1,flag2; 74 }t[maxn<<3]; 75 inline void Build(int k,int l,int r){ 76 t[k].l=l;t[k].r=r; 77 if(l==r){ 78 t[k].maxs=W[rev[l]]; 79 return; 80 } 81 int mid=(l+r)>>1,ls=k<<1,rs=k<<1|1; 82 Build(ls,l,mid);Build(rs,mid+1,r); 83 t[k].maxs=max(t[ls].maxs,t[rs].maxs); 84 return; 85 } 86 inline void Pushdown(int k){ 87 int ls=k<<1,rs=k<<1|1,flag1=t[k].flag1,flag2=t[k].flag2; 88 if(flag1){ 89 t[ls].maxs=t[rs].maxs=t[ls].flag1=t[rs].flag1=flag1; 90 t[ls].flag2=t[rs].flag2=0; 91 t[k].flag1=0; 92 } 93 if(flag2){ 94 t[ls].maxs+=flag2;t[rs].maxs+=flag2; 95 t[ls].flag2+=flag2;t[rs].flag2+=flag2; 96 t[k].flag2=0; 97 } 98 return; 99 } 100 inline void Update(int k,int ql,int qr,int v,int o){ 101 int l=t[k].l,r=t[k].r; 102 if(ql<=l&&r<=qr){ 103 if(o==0){ 104 t[k].maxs=v; 105 t[k].flag1=v; 106 t[k].flag2=0; 107 } 108 else { 109 t[k].maxs+=v; 110 t[k].flag2+=v; 111 } 112 return; 113 } 114 int mid=(l+r)>>1,ls=k<<1,rs=k<<1|1; 115 Pushdown(k); 116 if(ql<=mid)Update(ls,ql,qr,v,o); 117 if(mid+1<=qr)Update(rs,ql,qr,v,o); 118 t[k].maxs=max(t[ls].maxs,t[rs].maxs); 119 return; 120 } 121 inline void Query(int k,int ql,int qr){ 122 int l=t[k].l,r=t[k].r; 123 if(ql<=l&&r<=qr){ 124 Ans=max(Ans,t[k].maxs); 125 return; 126 } 127 int mid=(l+r)>>1,ls=k<<1,rs=k<<1|1; 128 Pushdown(k); 129 if(ql<=mid)Query(ls,ql,qr); 130 if(mid+1<=qr)Query(rs,ql,qr); 131 return; 132 } 133 inline void Solve(int x,int y,int v,int o){ 134 int fx=top[x],fy=top[y]; 135 while(fx!=fy){ 136 if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy); 137 if(o!=2)Update(1,seg[fx],seg[x],v,o); 138 else Query(1,seg[fx],seg[x]); 139 x=fa[top[x]];fx=top[x]; 140 } 141 if(dep[x]>dep[y])swap(x,y); 142 if(seg[x]==seg[y])return; 143 if(o!=2)Update(1,seg[x]+1,seg[y],v,o); 144 else Query(1,seg[x]+1,seg[y]); 145 return; 146 } 147 int main(){ 148 N=rd(); 149 for(int i=1;i<N;i++){ 150 a=rd();b=rd();c=rd(); 151 Add_edge(a,b,c); 152 Add_edge(b,a,c); 153 } 154 Dfs(1,0); 155 Dfs1(1,0); 156 seg[0]=seg[1]=rev[1]=top[1]=1; 157 Dfs2(1); 158 Build(1,1,N); 159 scanf("%s",o); 160 while(o[0]!='S'){ 161 a=rd();b=rd(); 162 if(o[0]!='M'){ 163 if(o[1]=='h'){//Change 164 if(E[a*2-1])Solve(edge[a*2-1].from,edge[a*2-1].to,b,0); 165 else Solve(edge[a*2].from,edge[a*2].to,b,0); 166 } 167 else if(o[1]=='o'){//Cover 168 c=rd(); 169 Solve(a,b,c,0); 170 } 171 else{//Add 172 c=rd(); 173 Solve(a,b,c,1); 174 } 175 } 176 else{//Max 177 Ans=0; 178 Solve(a,b,-1,2); 179 printf("%d\n",Ans); 180 } 181 scanf("%s",o); 182 } 183 return 0; 184 }

By:AlenaNuna