P2590 [ZJOI2008]树的统计
Posted 2529102757ab
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2590 [ZJOI2008]树的统计相关的知识,希望对你有一定的参考价值。
传送门
题目描述
一棵树上有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
说明
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。.
用一句话来形容,这是裸的!!!!
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 const int maxn=1e5+10; 8 struct node 9 10 int next; 11 int from; 12 int to; 13 way[maxn]; 14 int tot; 15 int head[maxn]; 16 int size[maxn]; 17 int sumv[maxn<<2]; 18 int maxv[maxn<<2]; 19 int father[maxn]; 20 int top[maxn]; 21 int son[maxn]; 22 int a[maxn<<2]; 23 int deep[maxn]; 24 const int inf=1e9+10; 25 int tuop[maxn]; 26 int n; 27 int pre[maxn]; 28 int cnt=0; 29 30 int add(int x,int y) 31 32 way[++tot].next=head[x]; 33 way[tot].to=y; 34 way[tot].from=x; 35 head[x]=tot; 36 37 38 void dfs1(int x,int fa) 39 40 size[x]=1; 41 for(int i=head[x];i;i=way[i].next) 42 43 int to=way[i].to; 44 if(to==fa) 45 46 continue; 47 48 deep[to]=deep[x]+1; 49 father[to]=x; 50 dfs1(to,x); 51 size[x]+=size[to]; 52 if(size[to]>size[son[x]]) 53 54 son[x]=to; 55 56 57 58 void dfs2(int x,int tp) 59 60 top[x]=tp; 61 tuop[x]=++cnt; 62 pre[cnt]=x; 63 if(son[x]) 64 65 dfs2(son[x],tp); 66 67 for(int i=head[x];i;i=way[i].next) 68 69 int to=way[i].to; 70 if(to==father[x]||to==son[x]) 71 continue; 72 dfs2(to,to); 73 74 75 inline void pushup(int x) 76 77 sumv[x]=sumv[x<<1]+sumv[(x<<1)^1]; 78 maxv[x]=max(maxv[x<<1],maxv[(x<<1)^1]); 79 80 void build(int x,int l,int r) 81 82 if(l==r) 83 84 sumv[x]=maxv[x]=a[pre[l]]; 85 return ; 86 87 int mid=(l+r)>>1; 88 build(x<<1,l,mid); 89 build((x<<1)^1,mid+1,r); 90 pushup(x); 91 92 void jia(int x,int l,int r,int q,int v) 93 94 if(l==r) 95 96 sumv[x]=maxv[x]=v; 97 return ; 98 99 int mid=(l+r)>>1; 100 if(q<=mid) 101 102 jia(x<<1,l,mid,q,v); 103 104 else 105 106 jia((x<<1)^1,mid+1,r,q,v); 107 108 pushup(x); 109 110 int cha(int x,int l,int r,int ls,int rs) 111 112 int ans=0; 113 if(ls<=l&&r<=rs) 114 115 return sumv[x]; 116 117 int mid=(l+r)>>1; 118 if(ls<=mid) 119 120 ans+=cha(x<<1,l,mid,ls,rs); 121 122 if(rs>mid) 123 124 ans+=cha((x<<1)^1,mid+1,r,ls,rs); 125 126 pushup(x); 127 return ans; 128 129 /*int chamax(int x,int l,int r,int ls,int rs) 130 131 int ans=-inf; 132 if(ls<=l&&r<=rs) 133 134 return maxv[x]; 135 136 int mid=(l+r)>>1; 137 if(ls<=mid) 138 139 ans=max(ans,chamax(x<<1,l,mid,ls,rs)); 140 141 if(rs>mid) 142 143 ans=max(ans,chamax((x<<1)^1,mid+1,r,ls,rs)); 144 145 pushup(x); 146 return ans; 147 */ 148 int chamax(int o,int l,int r,int ql,int qr) 149 int mid=(l+r)/2,ans=-inf; 150 if (ql<=l&&r<=qr)return maxv[o]; 151 if (ql<=mid)ans=max(ans,chamax(o*2,l,mid,ql,qr)); 152 if (qr>mid)ans=max(ans,chamax(o*2+1,mid+1,r,ql,qr)); 153 pushup(o); 154 return ans; 155 156 int qsum(int x,int to) 157 158 int ans=0; 159 while(top[x]!=top[to]) 160 161 if(deep[top[x]]<deep[top[to]]) 162 163 swap(x,to); 164 165 ans+=cha(1,1,n,tuop[top[x]],tuop[x]); 166 x=father[top[x]]; 167 168 if(deep[x]<deep[to]) 169 170 swap(x,to); 171 172 ans+=cha(1,1,n,tuop[to],tuop[x]); 173 return ans; 174 175 int qmax(int x,int to) 176 177 int ans=-inf; 178 while(top[x]!=top[to]) 179 180 if(deep[top[x]]<deep[top[to]]) 181 182 swap(x,to); 183 184 185 ans=max(ans,chamax(1,1,n,tuop[top[x]],tuop[x])); 186 x=father[top[x]]; 187 188 if(deep[x]<deep[to]) 189 190 swap(x,to); 191 192 ans=max(ans,chamax(1,1,n,tuop[to],tuop[x])); 193 return ans; 194 195 int main() 196 197 //freopen("www.out","w",stdout); 198 memset(a,0,sizeof(a)); 199 memset(head,0,sizeof(head)); 200 scanf("%d",&n); 201 for(int i=1;i<n;i++) 202 203 int u; 204 int v; 205 scanf("%d%d",&u,&v); 206 add(u,v); 207 add(v,u); 208 209 for(int i=1;i<=n;i++) 210 211 scanf("%d",&a[i]); 212 213 deep[1]=1; 214 father[1]=1; 215 dfs1(1,-1); 216 dfs2(1,1); 217 build(1,1,n); 218 int T; 219 scanf("%d",&T); 220 while(T--) 221 222 char flag[10]; 223 int x; 224 int y; 225 scanf("%s%d%d",flag,&x,&y); 226 if(flag[1]==‘H‘) 227 228 jia(1,1,n,tuop[x],y); 229 230 else 231 if(flag[1]==‘M‘) 232 233 printf("%d\n",qmax(x,y)); 234 235 else 236 if(flag[1]==‘S‘) 237 238 printf("%d\n",qsum(x,y)); 239 240 241 return 0; 242
以上是关于P2590 [ZJOI2008]树的统计的主要内容,如果未能解决你的问题,请参考以下文章