HDU 5692 线段树

点击打开链接

题意:中文题目

思路:这还是第一次写这样的线段树,个人感觉是一种套路之前没做过,但是思想什么巧妙,将一颗树转化成线段树真厉害,先是将每个节点的下面的所有数进行dfs编序号,并将他们的左右编号记下来,也就是我的代码中的L和R,而val记录的是根节点0到当前位置的费用,建树之后就很好操作了,更新时便找到当前节点的儿子和自己代表的区间,然后区间更新,注意题目说更新一个节点的值变为y,我们为什么更新一段,因为我们线段树的节点保存的是到根节点0的费用,那么作为一个父亲节点,它的值变了,自然会影响它的所有儿子到根节点的费用,而且变化的相同,所以用区间更新来完成,查询也是一样,必须到x节点,那么到了x节点后是不是还会有更大的费用呢,而这个费用的点肯定要经过x节点,所以我们直接查询x节点和它的所有儿子的最大值即可    PS:树形的结构与线段树完美结合,要好好练练才行

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int maxn=100010;
vectorG[maxn];
ll max1[maxn*4],lazy[maxn*4],val[maxn];
int L[maxn],R[maxn],cost[maxn];
int idx;
void dfs(int u,int f,ll vv){
    L[u]=++idx;
    for(unsigned int i=0;i>1;
    buildtree(le,t,node<<1);
    buildtree(t+1,ri,node<<1|1);
    pushup(node);
}
void update(int l,int r,int x,int le,int ri,int node){
    if(l<=le&&ri<=r){
        lazy[node]+=(ll)x;
        max1[node]+=(ll)x;
        return ;
    }
    pushdown(node);
    int t=(le+ri)>>1;
    if(l<=t) update(l,r,x,le,t,node<<1);
    if(r>t) update(l,r,x,t+1,ri,node<<1|1);
    pushup(node);
}
ll query(int l,int r,int le,int ri,int node){
    if(l<=le&&ri<=r) return max1[node];
    pushdown(node);
    ll ans=-inf;
    int t=(le+ri)>>1;
    if(l<=t) ans=max(ans,query(l,r,le,t,node<<1));
    if(r>t) ans=max(ans,query(l,r,t+1,ri,node<<1|1));
    return ans;
}
int main(){
    int T,cas=1,n,m,a,b,c;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=0;i

你可能感兴趣的:(线段树&树状数组,数据结构,线段树)