题目链接:https://cn.vjudge.net/contest/279350#problem/C
具体思路:单点更新,区间查询,查询的时候有两种操作,查询区间最大值和区间和。
注意点:在查询的时候,我们应该直接将这个点进行查询,而不是荆这个点在树上的编号进行查询,只有在进入线段树的时候我们才用树上的编号,update的时候也就直接用树上的编号就可以了,注意这个题有点权值会有负值的情况。
AC代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cmath> 4 #include<stack> 5 #include<iomanip> 6 #include<stdio.h> 7 #include<algorithm> 8 using namespace std; 9 # define ll long long 10 # define inf 0x3f3f3f3f 11 # define lson l,m,rt<<1 12 # define rson m+1,r,rt<<1|1 13 const int maxn = 60000+100; 14 int head[maxn],edgnum,sto[maxn],depth[maxn],Size[maxn],father[maxn]; 15 int son[maxn],ord[maxn],dfsnum,cost[maxn],top[maxn]; 16 int tree1[maxn<<2],tree2[maxn<<2]; 17 int maxx; 18 struct node 19 { 20 int fr; 21 int to; 22 int nex; 23 } edge[maxn]; 24 void addedge(int fr,int to) 25 { 26 edge[edgnum].fr=fr; 27 edge[edgnum].to=to; 28 edge[edgnum].nex=head[fr]; 29 head[fr]=edgnum++; 30 } 31 void dfs1(int fr,int rt,int dep) 32 { 33 depth[fr]=dep; 34 father[fr]=rt; 35 son[fr]=-1; 36 Size[fr]=1; 37 for(int i=head[fr]; i!=-1; i=edge[i].nex) 38 { 39 int to=edge[i].to; 40 if(to==rt) 41 continue; 42 dfs1(to,fr,dep+1); 43 Size[fr]+=Size[to]; 44 if(son[fr]==-1||Size[son[fr]]<Size[to]) 45 { 46 son[fr]=to; 47 } 48 } 49 } 50 void dfs2(int fr,int rt) 51 { 52 ord[fr]=++dfsnum; 53 top[fr]=rt; 54 cost[ord[fr]]=sto[fr]; 55 if(son[fr]!=-1) 56 { 57 dfs2(son[fr],rt); 58 } 59 for(int i=head[fr]; i!=-1; i=edge[i].nex) 60 { 61 int to=edge[i].to; 62 if(son[fr]!=to&&father[fr]!=to) 63 { 64 dfs2(to,to); 65 } 66 } 67 } 68 void up1(int rt) 69 { 70 tree1[rt]=max(tree1[rt<<1],tree1[rt<<1|1]); 71 } 72 void up2(int rt) 73 { 74 tree2[rt]=tree2[rt<<1]+tree2[rt<<1|1]; 75 } 76 void buildtree(int l,int r,int rt) 77 { 78 if(l==r) 79 { 80 tree1[rt]=cost[l]; 81 tree2[rt]=cost[l]; 82 return ; 83 } 84 int m=(l+r)>>1; 85 buildtree(lson); 86 buildtree(rson); 87 up1(rt); 88 up2(rt); 89 } 90 void query1(int l,int r,int rt,int L,int R) 91 { 92 if(L<=l&&R>=r) 93 { 94 maxx=max(maxx,tree1[rt]); 95 return ; 96 } 97 int m=(l+r)>>1; 98 if(L<=m) 99 query1(lson,L,R); 100 if(R>m) 101 query1(rson,L,R); 102 up1(rt); 103 } 104 void Query1(int n,int x,int y) 105 { 106 maxx=-inf; 107 int tx=top[x],ty=top[y]; 108 while(tx!=ty) 109 { 110 if(depth[tx]<depth[ty]) 111 { 112 swap(tx,ty); 113 swap(x,y); 114 } 115 query1(1,n,1,ord[tx],ord[x]); 116 x=father[tx],tx=top[x]; 117 } 118 if(depth[x]<depth[y]) 119 { 120 swap(x,y); 121 } 122 query1(1,n,1,ord[y],ord[x]); 123 } 124 int query2(int l,int r,int rt,int L,int R) 125 { 126 if(L<=l&&R>=r) 127 { 128 return tree2[rt]; 129 } 130 int ans=0; 131 int m=(l+r)>>1; 132 if(L<=m) 133 ans+=query2(lson,L,R); 134 if(R>m) 135 ans+=query2(rson,L,R); 136 up2(rt); 137 return ans; 138 } 139 int Query2(int n,int x,int y) 140 { 141 int tx=top[x],ty=top[y]; 142 int ans=0; 143 while(tx!=ty) 144 { 145 if(depth[tx]<depth[ty]) 146 { 147 swap(tx,ty); 148 swap(x,y); 149 } 150 ans+=query2(1,n,1,ord[tx],ord[x]); 151 x=father[tx],tx=top[x]; 152 } 153 if(depth[x]<depth[y]) 154 { 155 swap(x,y); 156 } 157 return ans+query2(1,n,1,ord[y],ord[x]); 158 } 159 void update(int l,int r,int rt,int pos,int p) 160 { 161 if(l==r) 162 { 163 tree1[rt]=p; 164 tree2[rt]=p; 165 return ; 166 } 167 int m=(l+r)>>1; 168 if(pos<=m) 169 update(lson,pos,p); 170 if(pos>m) 171 update(rson,pos,p); 172 up1(rt); 173 up2(rt); 174 } 175 int main() 176 { 177 int n; 178 scanf("%d",&n); 179 for(int i=1; i<=n; i++) 180 { 181 head[i]=-1; 182 } 183 int t1,t2; 184 for(int i=1; i<n; i++) 185 { 186 scanf("%d %d",&t1,&t2); 187 addedge(t1,t2); 188 addedge(t2,t1); 189 } 190 for(int i=1; i<=n; i++) 191 { 192 scanf("%d",&sto[i]); 193 } 194 dfs1(1,-1,1); 195 dfs2(1,1); 196 buildtree(1,n,1); 197 int q; 198 char str[100]; 199 scanf("%d",&q); 200 while(q--) 201 { 202 scanf("%s",str); 203 if(str[0]=='Q'&&str[1]=='M') 204 { 205 scanf("%d %d",&t1,&t2); 206 Query1(n,t1,t2); 207 printf("%d ",maxx); 208 } 209 else if(str[0]=='Q'&&str[1]=='S') 210 { 211 scanf("%d %d",&t1,&t2); 212 int ans=Query2(n,t1,t2); 213 printf("%d ",ans); 214 } 215 else if(str[0]=='C') 216 { 217 scanf("%d %d",&t1,&t2); 218 update(1,n,1,ord[t1],t2); 219 } 220 } 221 return 0; 222 }