[kuangbin]线段树

[kuangbin]线段树

2019.07.08

1.HDU 1166 敌兵布阵

1.1题目描述

​ 单点修改+区间查询

1.2代码

#include <cstdio>
#include <iostream>
#define mid ((tr[d].l + tr[d].r) >> 1)
#define sl d*2
#define sr d*2+1
using namespace std;
const int N = 50005;
int T,n;
int a[N];
string Q;
struct Tree{
    int l,r;
    int sum;
}tr[N*8];

void build(int d,int l,int r){
    tr[d].l = l,tr[d].r = r;
    if (l == r){
        tr[d].sum = a[l];
        return;
    }
    build(sl,l,mid);
    build(sr,mid+1,r);
    tr[d].sum = tr[sl].sum + tr[sr].sum;
}

void modify(int d,int x,int w){
    if (tr[d].l == x && tr[d].r == x){
        tr[d].sum += w;
        return;
    }
    if (x <= mid) modify(sl,x,w);
    else modify(sr,x,w);
    tr[d].sum = tr[sl].sum + tr[sr].sum;
}

int query(int d,int l,int r){
    if (tr[d].l == l && tr[d].r == r){
        return tr[d].sum;
    }
    if (r <= mid) return query(sl,l,r);
    else if (l > mid) return query(sr,l,r);
    else return query(sl,l,mid)+query(sr,mid+1,r);
}

int main(){
    scanf("%d",&T);
    for (int t = 1;t <= T;t++){
        scanf("%d",&n);
        for (int i = 1;i <= n;++i){
            scanf("%d",a+i);
        }
        printf("Case %d:\n",t);
        build(1,1,n);
        while(cin >> Q && Q != "End"){
            int u,v;
            scanf("%d%d",&u,&v);
            if (Q == "Query"){
                printf("%d\n",query(1,u,v));
            }else if (Q == "Add"){
                modify(1,u,v);
            }else if (Q == "Sub"){
                modify(1,u,-v);
            }
        }
    }
}

2.HDU 1754 I Hate It

2.1 题目描述

​ 单点修改+区间查询

2.2 代码

#include <cstdio>
#include <iostream>
#include <cmath>
#define mid ((tr[d].l + tr[d].r) >> 1)
#define sl d*2
#define sr d*2+1
using namespace std;
const int N = 200005;
int m,n,u,v;
int a[N];
string Q;
struct Tree{
    int l,r;
    int max;
}tr[N*8];

void build(int d,int l,int r){
    tr[d].l = l,tr[d].r = r;
    if (l == r){
        tr[d].max = a[l];
        return;
    }
    build(sl,l,mid);
    build(sr,mid+1,r);
    tr[d].max = max(tr[sl].max,tr[sr].max);
}

void modify(int d,int x,int w){
    if (tr[d].l == x && tr[d].r == x){
        tr[d].max = w;
        return;
    }
    if (x <= mid) modify(sl,x,w);
    else modify(sr,x,w);
    tr[d].max = max(tr[sl].max,tr[sr].max);
}

int query(int d,int l,int r){
    if (tr[d].l == l && tr[d].r == r){
        return tr[d].max;
    }
    if (r <= mid) return query(sl,l,r);
    else if (l > mid) return query(sr,l,r);
    else return max(query(sl,l,mid),query(sr,mid+1,r));
}

int main(){
    while(~scanf("%d%d",&n,&m)){
        for (int i = 1;i <= n;++i){
            scanf("%d",a+i);
        }
        build(1,1,n);
        for (int i = 0;i < m;++i){
            cin >> Q;
            scanf("%d%d",&u,&v);
            if (Q == "Q") printf("%d\n",query(1,u,v));
            if (Q == "U") modify(1,u,v);
        }
    }
}

3.POJ 3468 A Simple Problem with Integers

3.1 题目描述

​ 区间修改+区间查询

3.2 代码

#include <cstdio>
#include <iostream>
#include <cmath>
#define mid ((tr[d].l + tr[d].r) >> 1)
#define sl (d*2)
#define sr (d*2+1)
using namespace std;
const int N = 100005;
typedef long long ll;
int m,n,u,v,w;
int a[N];
string Q;
struct Tree{
    int l,r;
    ll sum,tag;
}tr[N*8];

int len(int d){
    return (tr[d].r - tr[d].l + 1);
}

void build(int d,int l,int r){
    tr[d].l = l,tr[d].r = r,tr[d].tag = 0;
    if (l == r){
        tr[d].sum = a[l];
        return;
    }
    build(sl,l,mid);
    build(sr,mid+1,r);
    tr[d].sum = tr[sl].sum + tr[sr].sum;
}

void pushdown(int d){
    tr[sl].sum += tr[d].tag*len(sl);
    tr[sr].sum += tr[d].tag*len(sr);
    tr[sl].tag += tr[d].tag;
    tr[sr].tag += tr[d].tag;
    tr[d].tag = 0;
}

void modify(int d,int l,int r,int w){
    if (tr[d].l == l && tr[d].r == r){
        tr[d].sum += w*(r-l+1);
        tr[d].tag += w;
        return;
    }
    pushdown(d);
    if (r <= mid) modify(sl,l,r,w);
    else if (l > mid) modify(sr,l,r,w);
    else {
        modify(sl,l,mid,w);
        modify(sr,mid+1,r,w);
    }
    tr[d].sum = tr[sl].sum + tr[sr].sum;
}

ll query(int d,int l,int r){
    if (tr[d].l == l && tr[d].r == r){
        return tr[d].sum;
    }
    pushdown(d);
    if (r <= mid) return query(sl,l,r);
    else if (l > mid) return query(sr,l,r);
    else return query(sl,l,mid) + query(sr,mid+1,r);
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i = 1;i <= n;++i) scanf("%d",a+i);
    build(1,1,n);
    for (int i = 1;i <= m;++i){
        cin >> Q;
        if (Q == "Q"){
            scanf("%d%d",&u,&v);
            printf("%lld\n",query(1,u,v));
        }else if (Q == "C"){
            scanf("%d%d%d",&u,&v,&w);
            modify(1,u,v,w);
        }
    }
    //system("pause");
    return 0;
}

4. POJ 2528 Mayor's posters

4.1题目描述

​ 区间修改+区间查询+离散化

4.2 题解

\(1 <= l_i <= r_i <= 10000000\) 需要离散化处理,同时如果离散化之后两个相邻点之间差大于1,需要在其中间插入一个点以确保不影响统计。

​ 离散化之前点数为2*N,离散化之后再算上插入的点,最多可达4*N。

4.3 代码

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define mid ((tr[d].l + tr[d].r) >> 1)
#define ls (d << 1)
#define rs ((d << 1) | 1)
using namespace std;
const int N = 40005;
int T,n,m;
int l[N],r[N],hash[N];
struct Tr{
    int l,r,w;
}tr[N*4];
int ans;
bool vis[N];
void build(int d,int l,int r){
    tr[d].l = l,tr[d].r = r,tr[d].w = -1;
    if (l == r){
        return;
    }
    build(ls,l,mid);
    build(rs,mid+1,r);
}

void pushdown(int d){
    if (tr[d].w == -1) return;
    tr[ls].w = tr[rs].w = tr[d].w;
    tr[d].w = -1;
}

void modify(int d,int l,int r,int w){
    if (tr[d].l == l && tr[d].r == r){
        tr[d].w = w;
        return;
    }
    pushdown(d);
    if (r <= mid) modify(ls,l,r,w);
    else if (l > mid) modify(rs,l,r,w);
    else {
        modify(ls,l,mid,w);
        modify(rs,mid+1,r,w);
    }

}

void query(int d,int l,int r){
    if (tr[d].w != -1){
        if (!vis[tr[d].w]){
            ans++;
            vis[tr[d].w] = 1;
        }
        return ;
    }
    if (tr[d].l == tr[d].r) return;
    pushdown(d);
    query(ls,l,mid);query(rs,mid+1,r);
}

int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        memset(vis,0,sizeof(vis));
        for (int i = 0;i < n;++i){
            scanf("%d%d",l+i,r+i);
            hash[i*2] = l[i],hash[i*2+1] = r[i];
        }
        sort(hash,hash+2*n);
        m = unique(hash,hash+2*n) - hash;
        int tmpM = m;
        for (int i = 1;i < tmpM;++i){
            if (hash[i] - hash[i-1] > 1){
                hash[m++] = hash[i-1] + 1;
            }
        }
        sort(hash,hash+m);
        build(1,0,m-1);
        for (int i = 0;i < n;++i){
            l[i] = lower_bound(hash,hash+m,l[i]) - hash;
            r[i] = lower_bound(hash,hash+m,r[i]) - hash;
            modify(1,l[i],r[i],i);
        }
        ans = 0;
        query(1,0,m-1);
        printf("%d\n",ans);

    }
    return 0;
}
posted @ 2020-02-11 20:06  mizersy  阅读(210)  评论(0编辑  收藏  举报