题目描述
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
我们将以下面的形式来要求你对这棵树完成一些操作:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身
输入输出格式
输入格式:输入文件的第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来一行n个整数,第i个整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
输出格式:对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
输入输出样例
输入样例#1:
复制
4 1 2 2 3 4 1 4 2 1 3 12 QMAX 3 4 QMAX 3 3 QMAX 3 2 QMAX 2 3 QSUM 3 4 QSUM 2 1 CHANGE 1 5 QMAX 3 4 CHANGE 3 6 QMAX 3 4 QMAX 2 4 QSUM 3 4
输出样例#1: 复制
4 1 2 2 10 6 5 6 5 16
说明
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
题解
先剖一下。
CHANGE:把dfn[x]处改为t
然后线段树同时维护两个值:mac(区间内最大值)和sum(区间和)
在修改的时候,先递归到叶子节点,然后在回溯的同时维护mac和sum,单次复杂度logn。
就星了。
1 /* 2 qwerta 3 P2590 [ZJOI2008]树的统计 4 Accepted 5 100 6 代码 C++,3.62KB 7 提交时间 2018-09-11 19:18:59 8 耗时/内存 9 3536ms, 6424KB 10 */ 11 #include<cmath> 12 #include<cstdio> 13 #include<iostream> 14 #include<algorithm> 15 using namespace std; 16 #define R register 17 #define LL long long 18 inline int read() 19 { 20 char ch=getchar(); 21 int x=0;bool s=1; 22 while(ch<'0'||ch>'9'){if(ch=='-')s=0;ch=getchar();} 23 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 24 return s?x:-x; 25 } 26 const int MAXN=30000+7; 27 struct emm{ 28 int e,f; 29 }b[2*MAXN]; 30 int h[MAXN]; 31 int tot=0; 32 void con(int x,int y) 33 { 34 b[++tot].f=h[x]; 35 h[x]=tot; 36 b[tot].e=y; 37 b[++tot].f=h[y]; 38 h[y]=tot; 39 b[tot].e=x; 40 return; 41 } 42 int s; 43 int d[MAXN],fa[MAXN],top[MAXN],siz[MAXN],z[MAXN]; 44 void dfs(int x) 45 { 46 siz[x]=1,top[x]=x; 47 int mac=0,macc=-1; 48 for(int i=h[x];i;i=b[i].f) 49 if(!d[b[i].e]) 50 { 51 d[b[i].e]=d[x]+1; 52 fa[b[i].e]=x; 53 dfs(b[i].e); 54 siz[x]+=siz[b[i].e]; 55 if(macc<siz[b[i].e]){mac=b[i].e,macc=siz[b[i].e];} 56 } 57 z[x]=mac; 58 top[mac]=x; 59 return; 60 } 61 int q[MAXN],dfn[MAXN]; 62 void dfss(int x) 63 { 64 q[++tot]=x; 65 dfn[x]=tot; 66 if(z[x])dfss(z[x]); 67 for(int i=h[x];i;i=b[i].f) 68 if(fa[b[i].e]==x&&b[i].e!=z[x]) 69 dfss(b[i].e); 70 return; 71 } 72 int fitop(int x) 73 { 74 if(top[x]==x)return x; 75 return top[x]=fitop(top[x]); 76 } 77 int val[MAXN]; 78 struct ahh{ 79 int l,r,mid,mac; 80 long long sum; 81 }a[8*MAXN]; 82 #define lz (i<<1) 83 #define rz ((i<<1)|1) 84 #define md a[i].mid 85 void build(int i,int ll,int rr) 86 { 87 a[i].l=ll; 88 a[i].r=rr; 89 if(ll==rr){a[i].mac=a[i].sum=val[q[ll]];return;} 90 md=(ll+rr)>>1; 91 build(lz,ll,md); 92 build(rz,md+1,rr); 93 a[i].mac=max(a[lz].mac,a[rz].mac); 94 a[i].sum=a[lz].sum+a[rz].sum; 95 return; 96 } 97 void change(int i,int x,int k) 98 { 99 if(a[i].l==a[i].r){a[i].mac=a[i].sum=k;return;} 100 if(x<=md)change(lz,x,k); 101 else change(rz,x,k); 102 a[i].mac=max(a[lz].mac,a[rz].mac); 103 a[i].sum=a[lz].sum+a[rz].sum; 104 return; 105 } 106 long long ans; 107 void findmac(int i,int ll,int rr) 108 { 109 if(a[i].l==ll&&a[i].r==rr){if(a[i].mac>ans)ans=a[i].mac;return;} 110 if(rr<=md)findmac(lz,ll,rr); 111 else if(md+1<=ll)findmac(rz,ll,rr); 112 else {findmac(lz,ll,md);findmac(rz,md+1,rr);} 113 return; 114 } 115 void findsum(int i,int ll,int rr) 116 { 117 if(a[i].l==ll&&a[i].r==rr){ans+=a[i].sum;return;} 118 if(rr<=md)findsum(lz,ll,rr); 119 else if(md+1<=ll)findsum(rz,ll,rr); 120 else {findsum(lz,ll,md);findsum(rz,md+1,rr);} 121 return; 122 } 123 int main() 124 { 125 //freopen("a.in","r",stdin); 126 int n; 127 cin>>n; 128 for(int i=1;i<n;++i) 129 { 130 int u,v; 131 cin>>u>>v; 132 con(u,v); 133 } 134 s=min(7,n); 135 d[s]=1; 136 dfs(s); 137 tot=0; 138 dfss(s); 139 for(int i=1;i<=n;++i) 140 top[i]=fitop(i); 141 for(int i=1;i<=n;++i) 142 cin>>val[i]; 143 build(1,1,n); 144 int q; 145 cin>>q; 146 for(int i=1;i<=q;++i) 147 { 148 string st; 149 cin>>st; 150 if(st[0]=='C') 151 { 152 int u,t; 153 cin>>u>>t; 154 change(1,dfn[u],t); 155 } 156 else if(st[1]=='M') 157 { 158 int u,v; 159 cin>>u>>v; 160 ans=-99999999999999; 161 while(top[u]!=top[v]) 162 { 163 if(d[top[u]]<d[top[v]])swap(u,v); 164 findmac(1,dfn[top[u]],dfn[u]); 165 u=fa[top[u]]; 166 } 167 if(d[u]<d[v])swap(u,v); 168 findmac(1,dfn[v],dfn[u]); 169 cout<<ans<<endl; 170 } 171 else 172 { 173 int u,v; 174 cin>>u>>v; 175 ans=0; 176 while(top[u]!=top[v]) 177 { 178 if(d[top[u]]<d[top[v]])swap(u,v); 179 findsum(1,dfn[top[u]],dfn[u]); 180 u=fa[top[u]]; 181 } 182 if(d[u]<d[v])swap(u,v); 183 findsum(1,dfn[v],dfn[u]); 184 cout<<ans<<endl; 185 } 186 } 187 return 0; 188 }