線段樹(單點更新)

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章