J. Ka Chang
Given a rooted tree ( the root is node 11 ) of NN nodes. Initially, each node has zero point.
Then, you need to handle QQ operations. There're two types:
1\ L\ X1 L X: Increase points by XX of all nodes whose depth equals LL ( the depth of the root is zero ). (x \leq 10^8)(x≤108)
2\ X2 X: Output sum of all points in the subtree whose root is XX.
Input
Just one case.
The first lines contain two integer, N,QN,Q. (N \leq 10^5, Q \leq 10^5)(N≤105,Q≤105).
The next n-1n−1 lines: Each line has two integer aa,bb, means that node aa is the father of node bb. It's guaranteed that the input data forms a rooted tree and node 11 is the root of it.
The next QQ lines are queries.
Output
For each query 22, you should output a number means answer.
样例输入复制
3 3 1 2 2 3 1 1 1 2 1 2 3
样例输出复制
1 0
题目来源
首先这是一个原题,你需要更新深度为x的值,每次仅仅查询子树就可以,用线段树的话,需要更新的太多的
要树分块,打上time标记,每个数据太多不能暴力更新,单独列出来
#include<bits/stdc++.h> using namespace std; const int N=100005; vector<int>G[N]; vector<int>pos[N]; vector<int>vec; int L[N],R[N]; int tot,n,m,lim=500; long long s[N],c[N]; void dfs(int now,int deep) { L[now]=++tot;//一块的左标记 pos[deep].push_back(L[now]); for(auto X:G[now])dfs(X,deep+1); R[now]=tot;//右标记,这个内全是其子树 return; } void add(int x,int d) { for(;x<=n;x+=x&-x)c[x]+=d; } long long sum(int x) { long long ans=0; for(;x>0;x-=x&-x)ans+=c[x]; return ans; } int main() { scanf("%d%d",&n,&m); for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),G[u].push_back(v); dfs(1,0); for(int i=0;i<=n;i++) if(pos[i].size()>lim)vec.push_back(i); for(int i=0,op,x,y;i<m;i++) { scanf("%d%d",&op,&x); if(op==1) { scanf("%d",&y); if(pos[x].size()<=lim) for(auto X:pos[x])add(X,y);//小于所给块大小,直接树状数组更新 else s[x]+=y;//大于的直接扔进去等更新 } else { long long ans=sum(R[x])-sum(L[x]-1);//查询所有小块的值,多余的进行下面的更新 for(auto X:vec) ans+=(upper_bound(pos[X].begin(), pos[X].end(),R[x])-lower_bound(pos[X].begin(),pos[X].end(),L[x]))*s[X]; //vec的元素不会太多,顶多1e5,直接搞进去更新 printf("%lld\n",ans); } } }
4765: 普通计算姬
Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1481 Solved: 318
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
Sample Output
#include<iostream> #include<vector> #include<math.h> using namespace std; #define N 100005 typedef unsigned long long ll; int n,m,q,lim,root,belong[N]; int L[N],R[N],tot,cnt[N]; int g[N][320]; ll c[N+N],sum[N],a[N],tag[N]; vector<int>G[N]; void add(int x,int d) { for(; x<=n; x+=x&-x)c[x]+=d; } ll Sum(int x) { ll ans=0; for(; x>0; x-=x&-x)ans+=c[x]; return ans; } void dfs(int x,int fa) { L[x]=++tot,add(L[x],a[x]),++cnt[belong[x]],sum[x]=a[x]; for(int i=1; i<=lim; i++)g[x][i]=cnt[i]; int l=G[x].size(); for(int i=0,X;i<l;i++) { X=G[x][i]; if(X==fa)continue; dfs(X,x); sum[x]+=sum[X]; } R[x]=tot,--cnt[belong[x]],tag[belong[x]]+=sum[x]; } ll query(int l,int r) { ll ans=0; for(int i=l;i<=min(r,belong[l]*m);i++)ans+=Sum(R[i])-Sum(L[i]-1); if(belong[l]!=belong[r]) { for(int i=(belong[r]-1)*m+1;i<=r;i++)ans+=Sum(R[i])-Sum(L[i]-1); } for(int i=belong[l]+1;i<=belong[r]-1;i++)ans+=tag[i]; return ans; } int main() { cin>>n>>q; m=sqrt(n+0.5);//一块有几个 for(int i=1; i<=n; i++)cin>>a[i],belong[i]=(i-1)/m+1; lim=belong[n]; for(int i=1,u,v; i<=n; ++i) { cin>>u>>v; if(!u)root=v; else G[u].push_back(v),G[v].push_back(u); } dfs(root,-1); for(int i=0,op,u,v; i<q; i++) { cin>>op>>u>>v; if(op==1) { for(int i=1; i<=lim; i++)tag[i]+=g[u][i]*1LL*(v-a[u]); add(L[u],v-a[u]),a[u]=v; } else cout<<query(u,v)<<"\n"; } return 0; }