线段树(单点更新)

来源:互联网 发布:高考软件文科 编辑:程序博客网 时间:2024/05/18 10:23

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|1struct 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<<31struct 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|1struct 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 200010struct 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;}


原创粉丝点击