题目链接:树的统计Count
树链剖分(权值在点上)[单点修改 询问区间和/最大值]:
int a[30005];
struct node
{
int tl,tr,maxx,sum;
node():maxx(0),sum(0) {}
} tree[120020];
void pushup(int id)
{
tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
tree[id].maxx=max(tree[id<<1].maxx,tree[id<<1|1].maxx);
}
void build(int id,int tl,int tr)
{
tree[id].tl=tl,tree[id].tr=tr;
if(tl==tr)
{
tree[id].maxx=a[tl];
tree[id].sum=a[tl];
}
else
{
int tm=(tl+tr)>>1;
build(id<<1,tl,tm);
build(id<<1|1,tm+1,tr);
pushup(id);
}
}
void update(int id,int wz,int val)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(tl==wz && wz==tr)
{
tree[id].maxx=val;
tree[id].sum=val;
}
else
{
int tm=(tl+tr)>>1;
if(tm>=wz)update(id<<1,wz,val);
else update(id<<1|1,wz,val);
pushup(id);
}
}
int get_max(int id,int ql,int qr)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(ql<=tl && tr<=qr)return tree[id].maxx;
int tm=(tl+tr)>>1,res1=-inf,res2=-inf;
if(tm>=ql)res1=get_max(id<<1,ql,qr);
if(tm<qr)res2=get_max(id<<1|1,ql,qr);
return max(res1,res2);
}
int get_sum(int id,int ql,int qr)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(ql<=tl && tr<=qr)return tree[id].sum;
int tm=(tl+tr)>>1;
int sum=0;
if(tm>=ql)sum+=get_sum(id<<1,ql,qr);
if(tm<qr)sum+=get_sum(id<<1|1,ql,qr);
return sum;
}
int pre[30005],siz[30005],dep[30005];
int top[30005],node_id[30005],heavy[30005];
int val[30005],idx=1;
vector<int>G[30005];
int dfs(int x,int fa,int depth)
{
dep[x]=depth,pre[x]=fa;
int res=1,maxx=0;
int len=G[x].size();
for(int i=0; i<len; i++)
{
if(G[x][i]==fa)continue;
int t=dfs(G[x][i],x,depth+1);
if(t>maxx)maxx=t,heavy[x]=G[x][i];
res+=t;
}
return siz[x]=res;
}
void slpf(int x,int fa,int tp)
{
node_id[x]=idx++;
top[x]=tp;
int len=G[x].size();
if(heavy[x])slpf(heavy[x],x,tp);
for(int i=0; i<len; i++)
{
int nex=G[x][i];
if(nex==fa)continue;
if(nex!=heavy[x])slpf(nex,x,nex);
}
}
int getmax(int x,int y)
{
int ans=-inf,res;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
res=get_max(1,node_id[top[x]],node_id[x]);
x=pre[top[x]];
}
else
{
res=get_max(1,node_id[top[y]],node_id[y]);
y=pre[top[y]];
}
if(res>ans)ans=res;
}
if(dep[x]>dep[y])swap(x,y);
res=get_max(1,node_id[x],node_id[y]);
if(res>ans)ans=res;
return ans;
}
int getsum(int x,int y)
{
int ans=0,res;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
res=get_sum(1,node_id[top[x]],node_id[x]);
x=pre[top[x]];
}
else
{
res=get_sum(1,node_id[top[y]],node_id[y]);
y=pre[top[y]];
}
ans+=res;
}
if(dep[x]>dep[y])swap(x,y);
res=get_sum(1,node_id[x],node_id[y]);
ans+=res;
return ans;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1; i<=n-1; i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1,0,1);
slpf(1,0,1);
for(int i=1; i<=n; i++)
scanf("%d",&a[node_id[i]]);
build(1,1,n);
int q;
scanf("%d",&q);
while(q--)
{
char op[10];
int x,y;
scanf("%s%d%d",op,&x,&y);
if(op[0]=='Q' && op[1]=='M')
printf("%d\n",getmax(x,y));
if(op[0]=='Q' && op[1]=='S')
printf("%d\n",getsum(x,y));
if(op[0]=='C')update(1,node_id[x],y);
}
return 0;
}
题目链接:树上操作
树链剖分(权值在点上)[单点/区间修改 询问区间和]:
struct node
{
int tl,tr;
ll lazy,sum;
node():lazy(0),sum(0) {}
}tree[400020];
int a[100005];
void pushup(int id)
{
tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
}
void build(int id,int tl,int tr)
{
tree[id].tl=tl,tree[id].tr=tr;
tree[id].lazy=tree[id].sum=0;
if(tl==tr)tree[id].sum=(ll)a[tl];
else
{
int tm=(tr+tl)>>1;
build(id<<1,tl,tm);
build(id<<1|1,tm+1,tr);
pushup(id);
}
}
void pushdown(int id)
{
if(!tree[id].lazy)return;
tree[id<<1].lazy+=tree[id].lazy;
tree[id<<1|1].lazy+=tree[id].lazy;
tree[id<<1].sum+=(tree[id<<1].tr-tree[id<<1].tl+1)*tree[id].lazy;
tree[id<<1|1].sum+=(tree[id<<1|1].tr-tree[id<<1|1].tl+1)*tree[id].lazy;
tree[id].lazy=0;
}
void update(int id,int ql,int qr,ll val)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(ql>tr || qr<tl)return;
if(ql<=tl && tr<=qr)
{
tree[id].lazy+=val;
tree[id].sum+=(tr-tl+1)*val;
return;
}
pushdown(id);
update(id<<1,ql,qr,val);
update(id<<1|1,ql,qr,val);
pushup(id);
}
ll get_sum(int id,int ql,int qr)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(ql>tr || qr<tl)return 0;
if(ql<=tl && tr<=qr)return tree[id].sum;
ll ans=0;
pushdown(id);
ans+=get_sum(id<<1,ql,qr);
ans+=get_sum(id<<1|1,ql,qr);
pushup(id);
return ans;
}
int pre[100005],siz[100005],dep[100005];
int top[100005],node_id[100005],heavy[100005];
int val[100005],lson[100005],rson[100005],idx=0;
vector<int>G[100005];
int dfs(int x,int fa,int depth)
{
dep[x]=depth,pre[x]=fa;
int res=1,maxx=0;
int len=G[x].size();
for(int i=0; i<len; i++)
{
if(G[x][i]==fa)continue;
int t=dfs(G[x][i],x,depth+1);
if(t>maxx)maxx=t,heavy[x]=G[x][i];
res+=t;
}
return siz[x]=res;
}
void slpf(int x,int fa,int tp)
{
lson[x]=node_id[x]=++idx;
top[x]=tp;
int len=G[x].size();
if(heavy[x])slpf(heavy[x],x,tp);
for(int i=0; i<len; i++)
{
int nex=G[x][i];
if(nex==fa)continue;
if(nex!=heavy[x])slpf(nex,x,nex);
}
rson[x]=idx;
}
ll getsum(int x,int y)
{
ll ans=0,res;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
res=get_sum(1,node_id[top[x]],node_id[x]);
x=pre[top[x]];
}
else
{
res=get_sum(1,node_id[top[y]],node_id[y]);
y=pre[top[y]];
}
ans+=res;
}
if(dep[x]>dep[y])swap(x,y);
res=get_sum(1,node_id[x],node_id[y]);
ans+=res;
return ans;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
for(int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1,0,1);
slpf(1,0,1);
for(int i=1;i<=n;i++)
a[node_id[i]]=val[i];
build(1,1,n);
while(q--)
{
int op,x;ll y;
scanf("%d",&op);
if(op==1)
{
scanf("%d%lld",&x,&y);
update(1,node_id[x],node_id[x],y);
}
if(op==2)
{
scanf("%d%lld",&x,&y);
update(1,lson[x],rson[x],y);
}
if(op==3)
{
scanf("%d",&x);
printf("%lld\n",getsum(1,x));
}
}
return 0;
}
题目链接:Query on a tree
树链剖分(权值在边上)[单点修改 询问区间最大值]:
int a[10005];
struct node
{
int tl,tr,val;
} tree[40020];
void pushup(int id)
{
tree[id].val=max(tree[id<<1].val,tree[id<<1|1].val);
}
void build(int id,int tl,int tr)
{
tree[id].tl=tl,tree[id].tr=tr;
if(tl==tr)tree[id].val=a[tl];
else
{
int tm=(tl+tr)>>1;
build(id<<1,tl,tm);
build(id<<1|1,tm+1,tr);
pushup(id);
}
}
void update(int id,int wz,int val)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(tl==wz && wz==tr)tree[id].val=val;
else
{
int tm=(tl+tr)>>1;
if(tm>=wz)update(id<<1,wz,val);
else update(id<<1|1,wz,val);
pushup(id);
}
}
int getval(int id,int ql,int qr)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(ql<=tl && tr<=qr)return tree[id].val;
int tm=(tl+tr)>>1,res1=0,res2=0;
if(tm>=ql)res1=getval(id<<1,ql,qr);
if(tm<qr)res2=getval(id<<1|1,ql,qr);
return max(res1,res2);
}
struct edge
{
int nex,id,val;
edge(int nex,int id,int val):
nex(nex),id(id),val(val) {}
};
int pre[10005],siz[10005],dep[10005];
int top[10005],edge_id[10005],heavy[10005];
int val[10005],ith[10005];
int idx=1;
vector<edge>G[10005];
void init(void)
{
idx=1;
memset(a,0,sizeof(a));
memset(ith,0,sizeof(ith));
memset(val,0,sizeof(val));
memset(top,0,sizeof(top));
memset(pre,0,sizeof(pre));
memset(siz,0,sizeof(siz));
memset(dep,0,sizeof(dep));
memset(heavy,0,sizeof(heavy));
memset(tree,0,sizeof(tree));
memset(edge_id,0,sizeof(edge_id));
}
int dfs(int x,int fa,int depth)
{
dep[x]=depth,pre[x]=fa;
int res=1,maxx=0;
int len=G[x].size();
for(int i=0; i<len; i++)
{
int nex=G[x][i].nex;
if(nex==fa)continue;
int t=dfs(nex,x,depth+1);
ith[G[x][i].id]=nex;
val[nex]=G[x][i].val;
if(t>maxx)
maxx=t,heavy[x]=nex;
res+=t;
}
return siz[x]=res;
}
void slpf(int x,int fa,int tp)
{
int len=G[x].size();
if(pre[x])edge_id[x]=idx++;
top[x]=tp;
if(heavy[x])slpf(heavy[x],x,tp);
for(int i=0; i<len; i++)
{
int nex=G[x][i].nex;
if(nex==fa)continue;
if(nex!=heavy[x])
slpf(nex,x,nex);
}
}
int getmax(int x,int y)
{
int ans=0,res;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
res=getval(1,edge_id[top[x]],edge_id[x]);
x=pre[top[x]];
}
else
{
res=getval(1,edge_id[top[y]],edge_id[y]);
y=pre[top[y]];
}
if(res>ans)ans=res;
}
if(dep[x]<dep[y])
{
if(edge_id[heavy[x]]<edge_id[y])
res=getval(1,edge_id[heavy[x]],edge_id[y]);
else res=getval(1,edge_id[y],edge_id[heavy[x]]);
}
if(dep[x]>dep[y])
{
if(edge_id[heavy[y]]<edge_id[x])
res=getval(1,edge_id[heavy[y]],edge_id[x]);
else res=getval(1,edge_id[x],edge_id[heavy[y]]);
}
if(res>ans)ans=res;
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
int n;
scanf("%d",&n);
for(int i=1; i<=n-1; i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
G[x].push_back(edge(y,i,z));
G[y].push_back(edge(x,i,z));
}
dfs(1,0,1);
slpf(1,0,1);
for(int i=1; i<=n; i++)
if(pre[i])a[edge_id[i]]=val[i];
build(1,1,n-1);
while(1)
{
char op[10];
int x,y;
scanf("%s",op);
if(op[0]=='D')break;
scanf("%d%d",&x,&y);
if(op[0]=='Q')printf("%d\n",getmax(x,y));
if(op[0]=='C')update(1,edge_id[ith[x]],y);
}
printf("\n");
for(int i=1; i<=n; i++)
G[i].clear();
}
return 0;
}
题目链接:Aragorn's Story
树链剖分(权值在点上)[区间修改 询问单点值]:
struct node
{
int tl,tr,lazy,sum;
node():lazy(0),sum(0) {}
}tree[200020];
int a[50005];
void pushup(int id)
{
tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
}
void build(int id,int tl,int tr)
{
tree[id].tl=tl,tree[id].tr=tr;
tree[id].lazy=tree[id].sum=0;
if(tl==tr)tree[id].sum=a[tl];
else
{
int tm=(tr+tl)>>1;
build(id<<1,tl,tm);
build(id<<1|1,tm+1,tr);
pushup(id);
}
}
void pushdown(int id)
{
if(!tree[id].lazy)return;
tree[id<<1].lazy+=tree[id].lazy;
tree[id<<1|1].lazy+=tree[id].lazy;
tree[id<<1].sum+=(tree[id<<1].tr-tree[id<<1].tl+1)*tree[id].lazy;
tree[id<<1|1].sum+=(tree[id<<1|1].tr-tree[id<<1|1].tl+1)*tree[id].lazy;
tree[id].lazy=0;
}
void update(int id,int ql,int qr,int val)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(ql>tr || qr<tl)return;
if(ql<=tl && tr<=qr)
{
tree[id].lazy+=val;
tree[id].sum+=(tr-tl+1)*val;
return;
}
pushdown(id);
update(id<<1,ql,qr,val);
update(id<<1|1,ql,qr,val);
pushup(id);
}
int get_sum(int id,int ql,int qr)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(ql>tr || qr<tl)return 0;
if(ql<=tl && tr<=qr)return tree[id].sum;
int ans=0;
pushdown(id);
ans+=get_sum(id<<1,ql,qr);
ans+=get_sum(id<<1|1,ql,qr);
pushup(id);
return ans;
}
int pre[50005],siz[50005],dep[50005];
int top[50005],node_id[50005],heavy[50005];
int val[50005],idx=0;
vector<int>G[50005];
int dfs(int x,int fa,int depth)
{
dep[x]=depth,pre[x]=fa;
int res=1,maxx=0;
int len=G[x].size();
for(int i=0; i<len; i++)
{
if(G[x][i]==fa)continue;
int t=dfs(G[x][i],x,depth+1);
if(t>maxx)maxx=t,heavy[x]=G[x][i];
res+=t;
}
return siz[x]=res;
}
void slpf(int x,int fa,int tp)
{
node_id[x]=++idx,top[x]=tp;
int len=G[x].size();
if(heavy[x])slpf(heavy[x],x,tp);
for(int i=0; i<len; i++)
{
int nex=G[x][i];
if(nex==fa)continue;
if(nex!=heavy[x])slpf(nex,x,nex);
}
}
void change(int x,int y,int z)
{
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
update(1,node_id[top[x]],node_id[x],z);
x=pre[top[x]];
}
else
{
update(1,node_id[top[y]],node_id[y],z);
y=pre[top[y]];
}
}
if(dep[x]>dep[y])swap(x,y);
update(1,node_id[x],node_id[y],z);
}
void init(void)
{
idx=0;
memset(a,0,sizeof(a));
memset(val,0,sizeof(val));
memset(top,0,sizeof(top));
memset(pre,0,sizeof(pre));
memset(siz,0,sizeof(siz));
memset(dep,0,sizeof(dep));
memset(heavy,0,sizeof(heavy));
memset(tree,0,sizeof(tree));
memset(node_id,0,sizeof(node_id));
}
int main()
{
int n,m,q;
while(~scanf("%d%d%d",&n,&m,&q))
{
init();
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1,0,1);
slpf(1,0,1);
for(int i=1;i<=n;i++)
a[node_id[i]]=val[i];
build(1,1,n);
while(q--)
{
char op[2];int x,y,z;
scanf("%s",op);
if(op[0]=='I')
{
scanf("%d%d%d",&x,&y,&z);
change(x,y,z);
}
if(op[0]=='D')
{
scanf("%d%d%d",&x,&y,&z);
change(x,y,-z);
}
if(op[0]=='Q')
{
scanf("%d",&x);
printf("%d\n",get_sum(1,node_id[x],node_id[x]));
}
}
for(int i=1;i<=n;i++)G[i].clear();
}
return 0;
}
题目链接:软件包管理器
树链剖分(权值在点上)[区间修改 询问区间和]:
struct node
{
int tl,tr,lazy,sum;
node():lazy(-1),sum(0) {}
}tree[400020];
inline void pushup(int id)
{
tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
}
void build(int id,int tl,int tr)
{
tree[id].tl=tl,tree[id].tr=tr;
if(tl==tr)tree[id].lazy=-1;
else
{
int tm=(tr+tl)>>1;
build(id<<1,tl,tm);
build(id<<1|1,tm+1,tr);
pushup(id);
}
}
void pushdown(int id)
{
if(tree[id].lazy==-1)return;
tree[id<<1].lazy=tree[id].lazy;
tree[id<<1|1].lazy=tree[id].lazy;
tree[id<<1].sum=(tree[id<<1].tr-tree[id<<1].tl+1)*tree[id].lazy;
tree[id<<1|1].sum=(tree[id<<1|1].tr-tree[id<<1|1].tl+1)*tree[id].lazy;
tree[id].lazy=-1;
}
void update(int id,int ql,int qr,int val)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(ql>tr || qr<tl)return;
if(ql<=tl && tr<=qr)
{
tree[id].lazy=val;
tree[id].sum=(tr-tl+1)*val;
return;
}
pushdown(id);
update(id<<1,ql,qr,val);
update(id<<1|1,ql,qr,val);
pushup(id);
}
int get_sum(int id,int ql,int qr)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(ql>tr || qr<tl)return 0;
if(ql<=tl && tr<=qr)return tree[id].sum;
int ans=0;
pushdown(id);
ans+=get_sum(id<<1,ql,qr);
ans+=get_sum(id<<1|1,ql,qr);
pushup(id);
return ans;
}
int uninall(int id,int ql,int qr)
{
int tl=tree[id].tl,tr=tree[id].tr;
if(ql>tr || qr<tl)return 0;
if(ql<=tl && tr<=qr)
{
int ans=tree[id].sum;
tree[id].lazy=0;
tree[id].sum=0;
return ans;
}
int ans=0;
pushdown(id);
ans+=uninall(id<<1,ql,qr);
ans+=uninall(id<<1|1,ql,qr);
pushup(id);
return ans;
}
int pre[100005],siz[100005],dep[100005];
int top[100005],node_id[100005],heavy[100005];
int lson[100005],rson[100005],idx=0;
struct
{
int nex,nex_node;
} edge[100005];
int head[100005],cont=0;
void add_edge(int now,int nex)
{
edge[cont].nex=nex;
edge[cont].nex_node=head[now];
head[now]=cont++;
}
int dfs(int x,int fa,int depth)
{
dep[x]=depth,pre[x]=fa;
int res=1,maxx=0;
for(int i=head[x];~i;i=edge[i].nex_node)
{
int nex=edge[i].nex;
if(nex==fa)continue;
int t=dfs(nex,x,depth+1);
if(t>maxx)maxx=t,heavy[x]=nex;
res+=t;
}
return siz[x]=res;
}
void slpf(int x,int fa,int tp)
{
lson[x]=node_id[x]=++idx;
top[x]=tp;
if(heavy[x])slpf(heavy[x],x,tp);
for(int i=head[x];~i;i=edge[i].nex_node)
{
int nex=edge[i].nex;
if(nex==fa)continue;
if(nex!=heavy[x])slpf(nex,x,nex);
}
rson[x]=idx;
}
int getsum(int x,int y,int z)
{
int ans=0,res;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
res=get_sum(1,node_id[top[x]],node_id[x]);
update(1,node_id[top[x]],node_id[x],z);
x=pre[top[x]];
}
else
{
res=get_sum(1,node_id[top[y]],node_id[y]);
update(1,node_id[top[y]],node_id[y],z);
y=pre[top[y]];
}
ans+=res;
}
if(dep[x]>dep[y])swap(x,y);
res=get_sum(1,node_id[x],node_id[y]);
update(1,node_id[x],node_id[y],z);
ans+=res;
return ans;
}
int main()
{
memset(head,-1,sizeof(head));
int n,t;
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
scanf("%d",&t);
add_edge(t+1,i);
}
dfs(1,0,1);
slpf(1,0,1);
build(1,1,n);
int q;
scanf("%d",&q);
while(q--)
{
char op[15];int x;
scanf("%s%d",op,&x);
if(op[0]=='i')
{
int res=getsum(x+1,1,1);
printf("%d\n",dep[x+1]-res);
}
else
{
int res=uninall(1,lson[x+1],rson[x+1]);
printf("%d\n",res);
}
}
return 0;
}
作者:fo0Old
链接:http://www.jianshu.com/p/03f365028725
來源:简书