BZOJ P2157 旅游

题目大意:

维护一棵树,每条边有边权,支持下列操作:
1.修改某条边的边权
2.将某条路经上的边权取反
3.询问某条路经上的和
4.询问某条路经上的最大值
5.询问某条路经上的最小值

                            --by BZOJ;

http://www.lydsy.com/JudgeOnline/problem.php?id=2157



有关树链剖分的详解,见:树链剖分

链剖模板,代码长了点,主要是线段树部分操作太多,注意可以把边权搞到点上;

代码如下:

  1 #include<cstdio>
  2 #define INF 0x3fffffff
  3 using namespace std;
  4 struct ss{
  5     int to,next,dis;
  6 }x[40001];
  7 int first[20001],num;
  8 int size[20001];//子树和// 
  9 int hway[20001];//重边//
 10 int rank[20001];//点在line_tree中的位置//
 11 int rankl[20001];//边所对点在line_tree中的位置// 
 12 int dis[20001];//点权 //
 13 int top[20001];//重链顶 //
 14 int dep[20001];//深度 //
 15 int fa[20001];//父亲// 
 16 int a[20001];//line_tree的原line序列// 
 17 int ltre[100005];
 18 int max[100005];
 19 int min[100005];
 20 int lz[100005];
 21 int n,m,L,R,X,W;
 22 void swap(int&,int&);
 23 void build(int ,int ,int );
 24 void dfs_1(int );
 25 void dfs_2(int ,int );
 26 void up(int );
 27 void down(int ,int ,int );
 28 void builtre(int ,int ,int );
 29 void work(int );
 30 int wor_(int ,int );
 31 void chan1(int ,int ,int );
 32 void chan2(int ,int ,int );
 33 int sum(int ,int ,int );
 34 int Max(int ,int ,int );
 35 int Min(int ,int ,int );
 36 int main()
 37 {
 38     int i,j,k,l;
 39     char s[50];
 40     scanf("%d",&n);
 41     for(i=0;i<=n-1;i++)
 42         hway[i]=i;
 43     for(i=1;i<=n-1;i++){
 44         scanf("%d%d%d",&j,&k,&l);
 45         build(j,k,l);
 46         build(k,j,l);
 47     }
 48     dep[0]=1;
 49     dfs_1(0);
 50     num=0;
 51     dfs_2(0,0);
 52     num=0;
 53     builtre(1,n,1);
 54     scanf("%d",&m);
 55     for(i=1;i<=m;i++){
 56         scanf("%s",s);
 57         scanf("%d%d",&L,&R);
 58         if(s[1]!='')s[0]=s[1];
 59         if(s[0]=='C')X=rankl[L],W=R;
 60         switch (s[0]){
 61             case 'C':    chan1(1,n,1);break;//C
 62             case 'N':    work(2);break;//N
 63             case 'U':    work(3);break;//NUM
 64             case 'A':    work(4);break;//MAX
 65             case 'I':    work(5);break;//MIN
 66             }
 67     }
 68 }
 69 void swap(int &a,int &b){
 70     int i;
 71     i=a;a=b;b=i;
 72 }
 73 void build(int f,int t,int l){
 74     x[++num].next=first[f];
 75     x[num].dis=l;
 76     x[num].to=t;
 77     first[f]=num;
 78 }
 79 void dfs_1(int now){
 80     int j=first[now];
 81     while(j){
 82         if(!dep[x[j].to]){
 83             dis[x[j].to]=x[j].dis;
 84             dep[x[j].to]=dep[now]+1;
 85             fa[x[j].to]=now;
 86             dfs_1(x[j].to);
 87             size[now]+=size[x[j].to];
 88             if(hway[now]==now||size[x[j].to]>size[hway[now]])
 89                 hway[now]=x[j].to;
 90         }
 91         j=x[j].next;
 92     }
 93     size[now]++;
 94 }
 95 void dfs_2(int now,int to_nu){
 96     int j=first[now];
 97     top[now]=to_nu;
 98     rank[now]=++num;
 99     a[num]=now;
100     if(hway[now]!=now)
101         dfs_2(hway[now],to_nu);
102     while(j){
103         if(dep[x[j].to]>dep[now]&&x[j].to!=hway[now])
104             rankl[(j+1)>>1]=num+1,dfs_2(x[j].to,x[j].to);
105         if(x[j].to==hway[now])
106             rankl[(j+1)>>1]=rank[hway[now]];
107         j=x[j].next;
108     }
109 }
110 void up(int nu){
111     ltre[nu]=ltre[nu<<1]+ltre[nu<<1|1];
112     max[nu]=max[nu<<1]>max[nu<<1|1]?max[nu<<1]:max[nu<<1|1];
113     min[nu]=min[nu<<1]<min[nu<<1|1]?min[nu<<1]:min[nu<<1|1];
114 }
115 void down(int l,int r,int nu){
116     if(!lz[nu])    return;
117     lz[nu<<1]^=1;lz[nu<<1|1]^=1;
118     swap(max[nu<<1],min[nu<<1]);
119     max[nu<<1]=-max[nu<<1];    min[nu<<1]=-min[nu<<1];
120     ltre[nu<<1]=-ltre[nu<<1];
121     swap(max[nu<<1|1],min[nu<<1|1]);
122     max[nu<<1|1]=-max[nu<<1|1];    min[nu<<1|1]=-min[nu<<1|1];
123     ltre[nu<<1|1]=-ltre[nu<<1|1];
124     lz[nu]=0;
125 }
126 void builtre(int l,int r,int nu){
127     if(l==r){
128         max[nu]=min[nu]=ltre[nu]=dis[a[++num]];
129         if(a[num]==0){
130             max[nu]=-INF;
131             min[nu]=INF;
132         }
133         return;
134     }
135     int mid=(l+r)>>1;
136     builtre(l,mid,nu<<1);
137     builtre(mid+1,r,nu<<1|1);
138     up(nu);
139 }
140 void work(int x){
141     int ans=0;
142     if(x==4)ans=-INF;
143     if(x==5)ans=INF;
144     int u=L,v=R;
145         while(top[u]!=top[v]){
146             if(dep[top[u]]<dep[top[v]])
147                 L=rank[top[v]],R=rank[v],v=fa[top[v]];
148             else
149                 L=rank[top[u]],R=rank[u],u=fa[top[u]];
150             ans=wor_(ans,x);
151         }
152         if(u!=v){
153             if(dep[u]>dep[v])
154                 swap(u,v);
155             u=hway[u];
156             L=rank[u];R=rank[v];
157             ans=wor_(ans,x);
158         }
159     if(x>=3)
160         printf("%d
",ans);
161 }
162 int wor_(int ans,int x){
163     int i;
164     if(x==2)
165         chan2(1,n,1);
166     if(x==3)
167         ans+=sum(1,n,1);
168     if(x==4){
169         i=Max(1,n,1);ans=ans>i?ans:i;}
170     if(x==5){
171         i=Min(1,n,1);ans=ans<i?ans:i;}
172     return ans;
173 }
174 void chan1(int l,int r,int nu){
175     if(l==r){
176         max[nu]=min[nu]=ltre[nu]=W ;
177         return;
178     }
179     int mid=(l+r)>>1;
180     down(l,r,nu);
181     if(X<=mid)
182         chan1(l,mid,nu<<1);
183     if(X>mid)
184         chan1(mid+1,r,nu<<1|1);
185     up(nu);
186 }
187 void chan2(int l,int r,int nu){
188     if(L<=l&&r<=R){
189         swap(max[nu],min[nu]);
190         max[nu]=-max[nu];
191         min[nu]=-min[nu];
192         ltre[nu]=-ltre[nu];
193         lz[nu]^=1;
194         return ;
195     }
196     down(l,r,nu);
197     int mid=(l+r)>>1;
198     if(L<=mid)
199         chan2(l,mid,nu<<1);
200     if(R>mid)
201         chan2(mid+1,r,nu<<1|1);
202     up(nu);
203 }
204 int sum(int l,int r,int nu){
205     if(L<=l&&r<=R)
206         return ltre[nu];
207     down(l,r,nu);
208     int mid=(l+r)>>1,re=0;
209     if(L<=mid)
210         re+=sum(l,mid,nu<<1);
211     if(R>mid)
212         re+=sum(mid+1,r,nu<<1|1);
213     return re;
214 }
215 int Max(int l,int r,int nu){
216     if(L<=l&&r<=R)
217         return max[nu];
218     down(l,r,nu);
219     int mid=(l+r)>>1,lm=-INF,rm=-INF;
220     if(L<=mid)
221         lm=Max(l,mid,nu<<1);
222     if(R>mid)
223         rm=Max(mid+1,r,nu<<1|1);
224     if(lm>=rm)
225         return lm;
226     return rm;
227 }
228 int Min(int l,int r,int nu){
229     if(L<=l&&r<=R)
230         return min[nu];
231     down(l,r,nu);
232     int mid=(l+r)>>1,lm=INF,rm=INF;
233     if(L<=mid)
234         lm=Min(l,mid,nu<<1);
235     if(R>mid)
236         rm=Min(mid+1,r,nu<<1|1);
237     if(lm<=rm)
238         return lm;
239     return rm;
240 }

祝AC哟;

原文地址:https://www.cnblogs.com/nietzsche-oier/p/6385110.html