树链剖分+线段树区间修改板子题
一道板子题写了两天。。。。。。一直在RE和WA。最后发现RE是因为一个int类函数没有返回值,WA是两个case情况写反了。
然后再说一下RE的问题,可能是除0,取余0,数组开小,还有就是函数的 类型和返回值不匹配(这种有些OJ会提示Exit code 4)
然后如果是返回值不匹配导致的RE有些OJ上用G++可以AC,但是Clong++是绝对不行的
树上操作
题目描述
有一棵点数为 N 的树,以点 1 为根,且树有点权。然后有 M 个操作,分为三种:
1.把某个节点 x 的点权增加 a 。
2.把某个节点 x 为根的子树中所有点的点权都增加 a 。
3.询问某个节点 x 到根的路径中所有点的点权和。
输入格式
第一行包含两个整数 N,M。表示点数和操作数。
接下来一行 N 个整数,表示树中节点的初始权值。
接下来 N−1 行每行两个正整数 fr,to , 表示该树中存在一条边 (fr,to) 。
再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类(1-3) ,之后接这个操作的参数(x 或者 x a) 。
输出格式
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
样例
输入
5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
输出
6
9
13
数据范围与提示
对于 100% 的数据, N,M≤1e5 ,且所有输入数据的绝对值都不会超过 1e6 。
题目出处:LibreOJ - 2125
#include<stdio.h>
#include<stdlib.h>
const int maxn=1e6+20;
typedef long long ll;
int to[maxn],nxt[maxn],n,q,first[maxn],cnt,tot;
ll w[maxn];
int dep[maxn],size[maxn],son[maxn],top[maxn],fa[maxn],idx[maxn],dfn[maxn];
struct tree{
int l,r;
ll sum,tag;
}seg[maxn<<1];
void add(int a,int b)
{
nxt[++cnt]=first[a];
to[cnt]=b;
first[a]=cnt;
}
void dfs1(int k,int f,int d)
{
fa[k]=f;
dep[k]=d;
size[k]=1;
if(first[k])
{
for(int j=first[k];j;j=nxt[j])
{
int v=to[j];
if(v==fa[k])
continue;
dfs1(v,k,d+1);
size[k]+=size[v];
if(size[v]>size[son[k]])
son[k]=v;
}
}
return;
}
void dfs2(int k,int tp)
{
dfn[k]=++tot;
top[k]=tp;
idx[tot]=k;
if(son[k])
{
dfs2(son[k],tp);
}
for(int j=first[k];j;j=nxt[j])
{
int v=to[k];
v=to[j];
if(v==fa[k]||v==son[k])
continue;
dfs2(v,v);
}
return;
}
void build(int k,int l,int r)
{
seg[k].l=l;
seg[k].r=r;
if(l==r)
{
seg[k].sum=w[idx[l]];
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
seg[k].sum=seg[2*k].sum+seg[2*k+1].sum;
return;
}
void pushdown(int k)
{
if(seg[k].l==seg[k].r)
return ;
if(seg[k].tag==0)
return ;
seg[2*k].sum+=seg[k].tag*(seg[2*k].r-seg[2*k].l+1);//注意是r-l不是l-r啊错了好几次
seg[2*k+1].sum+=seg[k].tag*(seg[2*k+1].r-seg[2*k+1].l+1);
seg[2*k].tag+=seg[k].tag;
seg[2*k+1].tag+=seg[k].tag;
seg[k].tag=0;
return ;
}
void update(int l,int r,ll nub,int k)
{
if(seg[k].l==l&&seg[k].r==r)
{
seg[k].tag+=nub;
seg[k].sum+=1ll*nub*(r-l+1);
return ;
}
pushdown(k);
int mid=seg[k].l+seg[k].r>>1;
if(r<=mid)
update(l,r,nub,k<<1);
else if(l>mid)
update(l,r,nub,(k<<1)|1);
else
{
update(l,mid,nub,k<<1);
update(mid+1,r,nub,(k<<1)|1);
}
seg[k].sum=seg[2*k].sum+seg[2*k+1].sum;
return ;
}
ll query(int l,int r,int k)
{
if(seg[k].l==l&&seg[k].r==r)
{
return seg[k].sum;
}
pushdown(k);
int mid=(seg[k].l+seg[k].r)>>1;
if(r<=mid)
return query(l,r,k<<1);
else if(l>mid)
return query(l,r,(k<<1)|1);
else
{
return query(l,mid,k<<1)+query(mid+1,r,(k<<1)|1);
}
}
void ask()//之前不知道咋想的这里是个int函数RE了两天
{
int x;
scanf("%d",&x);
ll ans=0;
while(top[x]!=1)
{
ans+=query(dfn[top[x]],dfn[x],1);
x=fa[top[x]];
}
ans+=query(dfn[top[x]],dfn[x],1);
printf("%lld\n",ans);
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%lld",&w[i]);
}
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
dfs1(1,0,1);
dfs2(1,1);
build(1,1,n);
while(q--)
{
int ty,x;
ll a;
scanf("%d",&ty);
switch(ty)
{
case 1: //错了好几次就是这个case1,2写反了
scanf("%d%lld",&x,&a);
update(dfn[x],dfn[x],a,1);
break;
case 2:
scanf("%d%lld",&x,&a);
update(dfn[x],dfn[x]+size[x]-1,a,1);
break;
case 3: ask();break;
}
}
return 0;
}
2021.7.26