线段树专题

敌兵布阵 HDU1166(单点修改 + 区间查询) 易

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PII pair<int, int>
#define PLI pair<ll, ll>
#define PIL pair<int, ll>
#define endl '\n'
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
#define debug(x) cerr << #x <<" = "<< x << endl
#define debug2(x, y) cerr << #x << " = " << x << " and " << #y << " = " << y << endl
#define Pi acos(-1)
using namespace std;

const int N = 1e5 + 100;

int sum[N << 2];

void pushup(int rt)
{
    sum[rt] = sum[rt << 1] + sum[rt << 1|1];
}

void build(int l, int r, int rt)
{
    if(l == r)
    {
        scanf("%d", &sum[rt]);
        return;
    }

    int m = (l + r) >> 1;

    build(lson);
    build(rson);

    pushup(rt);
}

void updata(int p, int add, int l, int r, int rt)
{
    if(l == r)
    {
        sum[rt] += add;
        return;
    }
    int m = (l + r) >> 1;

    if(p <= m) updata(p, add, lson);
    else updata(p, add, rson);

    pushup(rt);
}

int query(int L, int R, int l, int r, int rt)
{
    if(L <= l && r <= R)
        return sum[rt];
    
    int res = 0;

    int m = (l + r) >> 1;
    if(L <= m) res += query(L, R, lson);
    if(R > m) res += query(L, R, rson);

    return res;
}

int main() 
{
    int t;
    scanf("%d", &t);
    for(int i = 1; i <= t; i ++)
    {
        printf("Case %d:\n", i);
        int n;
        char a[100];
        scanf("%d", &n);
        getchar();
        build(1, n, 1);

        while(scanf("%s", a) && a[0] != 'E')
        {
            if(a[0] == 'Q')
            {
                int x, y;
                scanf("%d%d", &x, &y);
                printf("%d\n", query(x, y, 1, n, 1));
            }
            else
            {
                int x, y;
                scanf("%d%d", &x, &y);
                if(a[0] == 'A')
                    updata(x, y, 1, n, 1);
                else
                    updata(x, -y, 1, n, 1);
            }
        }
    }
    return 0;
}

木桩(单点修改 单点查询)每次找到一个无序区间中第一个大于某个数x的数y的位置,并修改这个数y

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PII pair<int, int>
#define PLI pair<ll, ll>
#define PIL pair<int, ll>
#define endl '\n'
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
#define debug(x) cerr << #x <<" = "<< x << endl
#define debug2(x, y) cerr << #x << " = " << x << " and " << #y << " = " << y << endl
#define Pi acos(-1)
using namespace std;

const int N = 1e5 + 100;

int mx[N << 2], a[N];

void pushup(int rt)
{
    mx[rt] = max(mx[rt << 1], mx[rt << 1|1]);
}

void build(int l, int r, int rt)
{
    if(l == r)
    {
        scanf("%d", &mx[rt]);
        return;
    }

    int m = (l + r) >> 1;
    build(lson);
    build(rson);

    pushup(rt);
}

void modify(int H, int h, int l, int r, int rt)
{
    if(mx[rt] < H) return;  //如果当前区间的最大值都没有比H大的
    						//直接返回
    if(l == r)    			//此时肯定是第一个大于H的数的位置
    {
        mx[rt] = h;
        return;
    }

    int m = (l + r) >> 1;
    if(mx[rt << 1] >= H) modify(H, h, lson);  //因为要找第一个,
    									//所以先看左边是否有
    else modify(H, h, rson);

    pushup(rt);
}

int query(int L, int R, int l, int r, int rt)
{
    if(l >= L && r <= R)
    {
        return mx[rt];
    }

    int res = -1;

    int m = (l + r) >> 1;
    if(m >= L) res = max(res,query(L, R, lson));
    if(m < R) res = max(res,query(L, R, rson));
    return res;
}

int main() 
{
    int t;
    scanf("%d", &t);
    while(t --)
    {
        int n, m;
        scanf("%d%d", &n, &m);

        build(1, n, 1);

        while(m --)
        {
            int H, h;
            scanf("%d%d", &H, &h);
            modify(H, h, 1, n, 1);
        }

        for(int i = 1; i <= n; i ++)
        {
            printf("%d", query(i, i, 1, n, 1));
            if(i != n) printf(" ");
        }
        puts("");
    }
    return 0;
}

Just a Hook HDU1698(区间修改)

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PII pair<int, int>
#define PLI pair<ll, ll>
#define PIL pair<int, ll>
#define endl '\n'
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
#define debug(x) cerr << #x <<" = "<< x << endl
#define debug2(x, y) cerr << #x << " = " << x << " and " << #y << " = " << y << endl
#define Pi acos(-1)
using namespace std;

const int N = 1e5 + 100;

int sum[N << 2], lz[N << 2];

void pushup(int x)
{
    sum[x] = sum[x << 1] + sum[x << 1|1];
}

void pushdown(int x, int m)  //区间求和懒标记
{
    if(lz[x])
    {
        lz[x << 1] = lz[x << 1|1] = lz[x];
        sum[x << 1] = (m - (m >> 1)) * lz[x]; //细节
        sum[x << 1|1] = (m >> 1) * lz[x];
        lz[x] = 0;
    }
}

void build(int l, int r, int rt)
{
    lz[rt] = 0;
    sum[rt] = 1;
    if(l == r)
        return;

    int m = (l + r) >> 1;

    build(lson);
    build(rson);

    pushup(rt);
}

void updata(int L, int R, int add, int l, int r, int rt)
{
    if(L <= l && r <= R)
    {
        sum[rt] = (r - l + 1) * add;
        lz[rt] = add;
        return ;
    }

    pushdown(rt, r - l + 1);  
    //这里是为了分裂,保证同一段区间上不存在两个lazy tag

    int m = (l + r) >> 1;

    if(m >= L) updata(L, R, add, lson);
    if(R > m) updata(L, R, add, rson);

    pushup(rt);
}

int main() 
{
    int t;
    scanf("%d", &t);
    for(int i = 1; i <= t; i ++)
    {
        int n, m;
        scanf("%d%d", &n, &m);
        build(1, n, 1);

        while(m --)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            updata(a, b, c, 1, n, 1);
        }
        printf("Case %d: The total value of the hook is %d.\n", i, sum[1]);
    }
    return 0;
}

POJ 3468(区间修改 区间查询)

#include<cstdio>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PII pair<int, int>
#define PLI pair<ll, ll>
#define PIL pair<int, ll>
#define endl '\n'
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
#define debug(x) cerr << #x <<" = "<< x << endl
#define debug2(x, y) cerr << #x << " = " << x << " and " << #y << " = " << y << endl
#define Pi acos(-1)
using namespace std;

const int N = 1e5 + 100;

ll sum[N << 2], lz[N << 2];

void pushup(int rt)
{
    sum[rt] = sum[rt << 1] + sum[rt << 1|1];
}

void pushdown(int rt, int m)
{
    if(lz[rt] != 0)
    {
        lz[rt << 1] += lz[rt];  //注意lz需要累加!
        lz[rt << 1|1] += lz[rt];
        sum[rt << 1] += (m - (m >> 1)) * lz[rt];
        sum[rt << 1|1] += (m >> 1) * lz[rt];
        lz[rt] = 0;
    }
}

void build(int l, int r, int rt)
{
    lz[rt] = 0;
    if(l == r)
    {
        scanf("%lld", &sum[rt]);
        return;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    pushup(rt);
}

void modify(int L, int R, int add, int l, int r, int rt)
{
    if(l >= L && r <= R)
    {
        sum[rt] += (ll)((r - l + 1) * add);
        lz[rt] += (ll)add;
        return ;
    }
    pushdown(rt, r - l + 1); 
    int m = (l + r) >> 1;
    if(m >= L) modify(L, R, add, lson);
    if(R > m) modify(L, R, add, rson);
    pushup(rt);
}

ll query(int L, int R, int l, int r, int rt)
{
    if(l >= L && r <= R)
        return sum[rt];
    pushdown(rt, r - l + 1);
    int m = (l + r) >> 1;
    ll res = 0;
    if(m >= L) res += query(L, R, lson);
    if(R > m) res += query(L, R, rson);
    return res;
}

int main() 
{
    int n, m;
    scanf("%d%d", &n, &m);
    build(1, n, 1);
    while(m --)
    {
        getchar();
        char c;
        int x, y, z;
        scanf("%c", &c);
        if(c == 'C')
        {
            scanf("%d%d%d", &x, &y, &z);
            modify(x, y, z, 1, n, 1);
        }
        else
        {
            scanf("%d%d", &x, &y);
            printf("%lld\n", query(x, y, 1, n, 1));
        }
    }
    return 0;
}

Mayor’s posters区间染色问题(离散化 + 线段树)。注意只需要pushdown,不需要pushup。

区间染色问题的离散化需要注意不能直接离散化。如果离散化后两个区间端点不是相邻的,则需要在两个数中间插入一个大小介于两个端点之间的值。

如1 4 6 10, 离散化后变为1 2 4 5 6 7 10

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define PIL pair<int, ll>
#define endl '\n'
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
#define debug(x) cerr << #x <<" = "<< x << endl
#define debug2(x, y) cerr << #x << " = " << x << " and " << #y << " = " << y << endl
#define Pi acos(-1)
using namespace std;

const int N = 1e4 + 100;

int ans[N << 4], bj[N << 4], cnt;

void pushdown(int rt)
{
    if(ans[rt] != -1) {
        ans[rt << 1] = ans[rt << 1|1] = ans[rt];
        ans[rt] = -1;
    }
}

void modify(int L, int R, int c, int l, int r, int rt)
{
    if(l >= L && r <= R)
    {
        ans[rt] = c;
        return;
    }

    pushdown(rt);
    int m = (l + r) >> 1;
    
    if(m >= L) modify(L, R, c, lson);
    if(m < R) modify(L, R, c, rson);
}

void query(int l, int r, int rt)
{
    if(bj[ans[rt]] == 0)
    {
        cnt ++;
        bj[ans[rt]] = 1;
        return;
    }
    if(l == r) return;
    pushdown(rt);
    int m = (l + r) >> 1;
    query(lson);
    query(rson);
}

int main() 
{
    int _;
    cin >> _;
    while(_ --)
    {
        cnt = 0;
        vector<PII> col;
        vector<int> hs, now;
        int n, m = 0;
        cin >> n;
        for(int i = 0; i < n; i ++)
        {
            int x, y;
            cin >> x >> y;
            col.push_back({x, y});
            hs.push_back(x),hs.push_back(y);
        }

        sort(hs.begin(), hs.end());
        hs.erase(unique(hs.begin(), hs.end()), hs.end());
        now.push_back(hs[0]);
        for(int i = 1; i < hs.size(); i ++) {
            if(hs[i] - hs[i - 1] > 1) now.push_back(hs[i - 1] + 1);
            now.push_back(hs[i]);
        }
        memset(ans, -1, sizeof ans);

        for(int i = 0; i < col.size(); i ++)
        {
            int l = lower_bound(now.begin(), now.end(), col[i].first) - now.begin();  //vector的二分,返回的是下标
            int r = lower_bound(now.begin(), now.end(), col[i].second) - now.begin();
            modify(l, r, i, 0, now.size() - 1, 1);
        }

        query(0, now.size() - 1, 1);
        cout << cnt << endl;
        memset(bj, 0, sizeof bj);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值