这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
2020-2021:teams:no_morning_training:shaco:知识点:数据结构:线段树 [2020/05/27 18:10] shaco |
2020-2021:teams:no_morning_training:shaco:知识点:数据结构:线段树 [2020/05/27 18:15] (当前版本) shaco |
||
---|---|---|---|
行 8: | 行 8: | ||
二叉树的结构,每一个节点代表一个区间,每个子节点代表父结点区间的一半。 | 二叉树的结构,每一个节点代表一个区间,每个子节点代表父结点区间的一半。 | ||
初始版本左儿子下标是父亲下标的两倍,右儿子下标为父亲下标的两倍+1。 | 初始版本左儿子下标是父亲下标的两倍,右儿子下标为父亲下标的两倍+1。 | ||
- | ==== 操作 ==== | + | ===== 操作 ===== |
- | === 建树 === | + | (代码源于网上) |
+ | ==== 建树 ==== | ||
自上而下,同时更新父节点。 | 自上而下,同时更新父节点。 | ||
<hidden code> | <hidden code> | ||
行 31: | 行 32: | ||
} | } | ||
} | } | ||
- | </hidden> | ||
</code> | </code> | ||
- | === 点更新 === | + | </hidden> |
+ | ==== 点更新 ==== | ||
自上而下 | 自上而下 | ||
<hidden code> | <hidden code> | ||
行 52: | 行 53: | ||
</code> | </code> | ||
</hidden> | </hidden> | ||
- | === 区间查询 === | + | ==== 区间查询 ==== |
自上而下,只统计所查询区间的子区间,在某一个递归进程中查询到则该进程结束。 | 自上而下,只统计所查询区间的子区间,在某一个递归进程中查询到则该进程结束。 | ||
<hidden code> | <hidden code> | ||
行 74: | 行 75: | ||
</code> | </code> | ||
</hidden> | </hidden> | ||
- | === 区间更新 === | + | ==== 区间更新 ==== |
使用lazy_tag,更新时只下放到最高一层的更新区间的子区间。查询时再更细致地下放。 | 使用lazy_tag,更新时只下放到最高一层的更新区间的子区间。查询时再更细致地下放。 | ||
<hidden code> | <hidden code> | ||
行 106: | 行 107: | ||
</code> | </code> | ||
</hidden> | </hidden> | ||
+ | ===== 例题 ===== | ||
+ | [[https://ac.nowcoder.com/acm/problem/13891|The Trip On Abandoned Railway]] | ||
+ | <hidden mycode> | ||
+ | <code cpp> | ||
+ | #include<cstdio> | ||
+ | #include<cstring> | ||
+ | #define INF 1000000007 | ||
+ | using namespace std; | ||
+ | int t,n,m,d,p[100005],T[500005]; | ||
+ | long long tag[500005][3]; | ||
+ | void push_down(int k) | ||
+ | { | ||
+ | tag[k<<1][0]+=tag[k][0]; | ||
+ | tag[k<<1][1]+=tag[k][1]; | ||
+ | tag[k<<1][2]+=tag[k][2]; | ||
+ | tag[k<<1|1][0]+=tag[k][0]; | ||
+ | tag[k<<1|1][1]+=tag[k][1]; | ||
+ | tag[k<<1|1][2]+=tag[k][2]; | ||
+ | tag[k][0]=tag[k][1]=tag[k][2]=0; | ||
+ | } | ||
+ | void update(int L,int R,int l,int r,int k,int startup,int quota) | ||
+ | { | ||
+ | if(l>=L&&r<=R) | ||
+ | { | ||
+ | tag[k][0]++; | ||
+ | tag[k][1]+=startup; | ||
+ | tag[k][2]+=quota; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | push_down(k); | ||
+ | int mid=(l+r)/2; | ||
+ | if(L<=mid) | ||
+ | update(L,R,l,mid,k<<1,startup,quota); | ||
+ | if(R>mid) | ||
+ | update(L,R,mid+1,r,k<<1|1,startup,quota); | ||
+ | } | ||
+ | } | ||
+ | int query(int k,int target,int l,int r) | ||
+ | { | ||
+ | if(l==r) | ||
+ | { | ||
+ | int ans=(T[k]+tag[k][2]%INF+((tag[k][0]*l-tag[k][1])*d)%INF)%INF; | ||
+ | T[k]=tag[k][0]=tag[k][1]=tag[k][2]=0; | ||
+ | return ans; | ||
+ | } | ||
+ | push_down(k); | ||
+ | int mid=(l+r)>>1; | ||
+ | if(target<=mid) | ||
+ | return query(k<<1,target,l,mid); | ||
+ | return query(k<<1|1,target,mid+1,r); | ||
+ | } | ||
+ | void build(int now,int l,int r) | ||
+ | { | ||
+ | if(l==r) | ||
+ | T[now]=p[l]; | ||
+ | else | ||
+ | { | ||
+ | int mid=(l+r)>>1; | ||
+ | build(now<<1,l,mid); | ||
+ | build(now<<1|1,mid+1,r); | ||
+ | } | ||
+ | } | ||
+ | int main() | ||
+ | { | ||
+ | scanf("%d",&t); | ||
+ | while(t--) | ||
+ | { | ||
+ | memset(T,0,sizeof(T)); | ||
+ | memset(tag,0,sizeof(tag)); | ||
+ | scanf("%d%d%d",&n,&m,&d); | ||
+ | for(int i=1;i<=n;i++) | ||
+ | scanf("%d",&p[i]); | ||
+ | build(1,1,n); | ||
+ | for(int i=1,op,x,y;i<=m;i++) | ||
+ | { | ||
+ | scanf("%d",&op); | ||
+ | if(op==1) | ||
+ | { | ||
+ | scanf("%d%d",&x,&y); | ||
+ | update(x,n,1,n,1,x,y); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | scanf("%d",&x); | ||
+ | printf("%d\n",query(1,x,1,n)); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
+ | </hidden> |