AlenaNuna

导航

树剖+线段树||树链剖分||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

posted on 2018-12-27 21:41  AlenaNuna  阅读(123)  评论(0编辑  收藏  举报