hdu 1698 Just a Hook || 2008 “Sunline Cup” National Invitational Contest || 线段树

hdu 1698 Just a Hook 请戳

  1. 题意:
    小疯子想玩玩金银铜这个游戏,现在给 n 个铜子(这个其实是为了照应后来的两子),她可以通过一种操作(x, y, z)把从第 x 到 第 y 的位置上的某子变成 z 所代表的某子。(1代表铜子, 2 代表银子, 3代表金子)
    那么问题来了:1 到 n 的代表值总共有多少呢?

  2. 思路:
    区间修改自然线段树,只是懒惰操作的方式各有不同,小傻子觉得通过值来来做懒惰操作比较简单和直观。
    下面是小傻子版做法,之后也给出网上比较给力的模版!

  3. 复杂度:
    时间复杂度:O(n * log(n))
    空间复杂度:O(4 * n)

  4. 代码:
    小傻子个人版

/* ***********************************************
Author        :Ilovezilian
Created Time  :2015/9/4 22:55:04
File Name     :seg_tree_4.cpp
************************************************ */

#include <bits/stdc++.h>
#define INF 0x7fffffff
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int N = 1e5+10, mod = 1e9+7;

int po[N<<2], kcas = 1;

void pushdown(int rt)
{
    po[rt<<1] = po[rt<<1|1] = po[rt], po[rt] = -1; //用-1座位懒惰标记
}

void build(int val, int l, int r, int rt)
{
    po[rt] = val; //如果用值作为标记,那么通常build的时间就省了。
}

void update(int val, int L, int R, int l, int r, int rt)
{
    if(L <= l && r <= R)
    {
        po[rt] = val;
        return;
    }

    if(po[rt] != -1) pushdown(rt);
    int m = (l + r) >> 1;
    if(L <= m) update(val, L, R, lson);
    if(R > m) update(val, L, R, rson);
}

int query(int L, int R, int l, int r, int rt)
{
    if(po[rt] != -1)
    {
        return (r - l + 1) * po[rt];
    }

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

void solve()
{
    int n, q, x, y, op;
    scanf("%d%d", &n, &q);
    build(1, 1, n, 1);

    for(int i = 0; i < q; i ++)
    {
        scanf("%d%d%d", &x, &y, &op);
        update(op, x, y, 1, n, 1);
    }

    printf("Case %d: The total value of the hook is %d.\n", kcas ++, query(1, n, 1, n, 1));
}

int main()
{
    //freopen("","r",stdin);
    //freopen("","w",stdout);
    int cas;
    scanf("%d", &cas);
    while(cas --) solve();
    return 0;
}

模版

#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

const int maxn = 111111;
int h, w, n;
int col[maxn<<2];
int sum[maxn<<2];
void pushup(int rt)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}

void pushdown(int rt, int m)
{
    if(col[rt]) 
    {
        col[rt<<1] = col[rt<<1|1] = col[rt];
        sum[rt<<1] = (m - (m >> 1)) * col[rt];
        sum[rt<<1|1] = (m>>1) * col[rt];
        col[rt] = 0;
    }
}

void build(int l, int r, int rt)
{
    col[rt] = 0;
    sum[rt] = 1;
    if(l == r) return;
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    pushup(rt);
}

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

int main()
{
    int T, n, m;
    scanf("%d", &T);
    for(int cas = 1; cas <= T; cas ++)
    {
        scanf("%d%d", &n, &m);
        build(1, n, 1);
        while(m --)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            update(a, b, c, 1, n, 1);
        }
        printf("Case %d: The total value of the hook is %d.\n", cas, sum[1]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值