线段树(单点更新)

1. hdu 1166 敌兵布阵

单点更新,区间求和,最裸的线段树

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 50010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Tree{
    int l,r,num;
}tree[maxn<<2];
void pushup(int rt){
    tree[rt].num=tree[rt<<1].num+tree[rt<<1|1].num;
}
void build(int l,int r,int rt){
    tree[rt].l=l;
    tree[rt].r=r;
    if(l==r){
        scanf("%d",&tree[rt].num);
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int pos,int val,int rt){
    int l,r;
    l=tree[rt].l;
    r=tree[rt].r;
    if(l==r){
        tree[rt].num+=val;
        return ;
    }
    int m=(l+r)>>1;
    if(pos<=m) update(pos,val,rt<<1);
    else update(pos,val,rt<<1|1);
    pushup(rt);
}
int query(int x,int y,int rt){
    int l,r;
    l=tree[rt].l;
    r=tree[rt].r;
    if(x==l && y==r){
        return tree[rt].num;
    }
    int m=(l+r)>>1;
    int ans=0;
    if(y<=m) ans+=query(x,y,rt<<1);
    else if(m<x) ans+=query(x,y,rt<<1|1);
    else {
        ans+=query(x,m,rt<<1);
        ans+=query(m+1,y,rt<<1|1);
    }
    return ans;
}
int main(){
    int T;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        printf("Case %d:\n",cas);
        int n;
        scanf("%d",&n);
        build(1,n,1);
        char op[10];
        int x,y;
        while(~scanf("%s",op)){
            if(op[0]=='E')  break;
            scanf("%d%d",&x,&y);
            if(op[0]=='A') update(x,y,1);
            else if(op[0]=='S') update(x,-y,1);
            else    printf("%d\n",query(x,y,1));
        }
    }
    return 0;
}

2. hdu 1754 I Hate It

单点更新,区间求最值,裸线段树

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 200010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 1<<31
struct Tree{
    int l,r,num;
}tree[maxn<<2];
void pushup(int rt){
    tree[rt].num=max(tree[rt<<1].num,tree[rt<<1|1].num);
}
void build(int l,int r,int rt){
    tree[rt].l=l;
    tree[rt].r=r;
    if(l==r){
        scanf("%d",&tree[rt].num);
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int pos,int var,int rt){
    int l,r;
    l=tree[rt].l;
    r=tree[rt].r;
    if(l==r){
        tree[rt].num=var;
        return ;
    }
    int m=(l+r)>>1;
    if(pos<=m) update(pos,var,rt<<1);
    else update(pos,var,rt<<1|1);
    pushup(rt);
}
int query(int x,int y,int rt){
    int l,r;
    l=tree[rt].l;
    r=tree[rt].r;
    if(l==x && y==r){
        return tree[rt].num;
    }
    int m=(l+r)>>1;
    int ans=-inf;
    if(x<=m) ans=max(ans,query(x,min(m,y),rt<<1));
    if(m<y) ans=max(ans,query(max(m+1,x),y,rt<<1|1));
    return ans;
}
int main(){
    int m,n;
    while(scanf("%d%d",&n,&m)!=EOF){
        build(1,n,1);
        char op[10];
        int x,y;
        while(m--){
            scanf("%s%d%d",op,&x,&y);
            if(op[0]=='Q')  printf("%d\n",query(x,y,1));
            else update(x,y,1);
        }
    }
    return 0;
}



3. hdu 1394 Minimum Inversion Number

求滚动之后,逆序对最少的对数,建一个节点值为0的线段树,每次插进去一个数之后,更新比他大的节点全部加1

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 5050
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Tree{
    int l,r,num;
}tree[maxn];
int num[maxn];
void pushup(int rt){
    tree[rt].num=tree[rt<<1].num+tree[rt<<1|1].num;
}
void build(int l,int r,int rt){
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].num=0;
    if(l==r) return ;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
void update(int pos,int rt){
    int l=tree[rt].l;
    int r=tree[rt].r;
    tree[rt].num++;
    if(l==r) return ;
    int m=(l+r)>>1;
    if(pos<=m) update(pos,rt<<1);
    else update(pos,rt<<1|1);
}
int query(int x,int y,int rt){
    int l=tree[rt].l;
    int r=tree[rt].r;
    if(x==l && y==r){
        return tree[rt].num;
    }
    int ans=0;
    int m=(l+r)>>1;
    if(y<=m) ans+=query(x,y,rt<<1);
    else if(m<x) ans+=query(x,y,rt<<1|1);
    else {
        ans+=query(x,m,rt<<1);
        ans+=query(m+1,y,rt<<1|1);
    }
    return ans;
}
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        build(1,n,1);
        int ans=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&num[i]);
            ans+=query(num[i]+1,n,1);
            update(num[i]+1,1);
        }
        int mx=ans;
        for(int i=1;i<=n;i++){
            ans=ans-num[i]+n-1-num[i];
            mx=min(mx,ans);
        }
        printf("%d\n",mx);
    }
    return 0;
}


4. hdu 2795 billboard

广告牌,每层至多放总宽为w的广告,每次放的时候优先考虑最上面最左边的位置,问每次放的位置的排数,不能放输出-1

线段树初始值维护一个最大值,对于当前节点,能放就放然后节点值减小val,并更新到父亲节点。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 200010
struct Tree{
    int l,r,num;
}tree[maxn<<2];
int h,w,n;
void pushup(int rt){
    tree[rt].num=max(tree[rt<<1].num,tree[rt<<1|1].num);
}
void build(int l,int r,int rt){
    tree[rt].l=l;
    tree[rt].r=r;
    if(l==r){
        tree[rt].num=w;
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
int query(int val,int rt){
    int l=tree[rt].l;
    int r=tree[rt].r;
    if(l==r){
        if(tree[rt].num<val)
            return -1;
        else{
            tree[rt].num-=val;
            return l;
        }
    }
    int ret;
    if(tree[rt<<1].num>=val)
        ret=query(val,rt<<1);
    else
        ret=query(val,rt<<1|1);
    pushup(rt);
    return ret;
}
int main(){
    while(scanf("%d%d%d",&h,&w,&n)!=EOF){
        h=min(h,n);
        build(1,h,1);
        int val;
        for(int i=1;i<=n;i++){
            scanf("%d",&val);
            printf("%d\n",query(val,1));
        }
    }
    return 0;
}


5. CF 197div2 D. Xenia and Bit Operations

题意:求一排数字的位运算的结果,建好树之后从下往上,异或和或交替运算。

思路:距离叶子节点距离为奇数的节点操作为异或更新,距离为偶数的为或操作更新。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn (1<<17)
struct Tree{
    int l,r,num,deep;
}tree[(maxn<<2)+1];
void pushup(int rt){
    tree[rt].deep=tree[rt<<1].deep+1;
    if(tree[rt].deep&1)
        tree[rt].num=tree[rt<<1].num^tree[rt<<1|1].num;
    else
        tree[rt].num=tree[rt<<1].num|tree[rt<<1|1].num;
}
void build(int l,int r,int rt){
    tree[rt].l=l;
    tree[rt].r=r;
    if(l==r){
        tree[rt].deep=1;
        scanf("%d",&tree[rt].num);
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int pos,int val,int rt){
    int l=tree[rt].l;
    int r=tree[rt].r;
    if(l==r){
        tree[rt].num=val;
        return ;
    }
    int m=(l+r)>>1;
    if(pos<=m) update(pos,val,rt<<1);
    else update(pos,val,rt<<1|1);
    pushup(rt);
}
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        build(1,(1<<n),1);
        int x,y;
        while(m--){
            scanf("%d%d",&x,&y);
            update(x,y,1);
            printf("%d\n",tree[1].num);
        }
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值