hdu 4893 Wow! Such Sequence!(线段树)

题目链接:hdu 4983 Wow! Such Sequence!

题目大意:就是三种操作
1 k d, 改动k的为值添加d
2 l r, 查询l到r的区间和
3 l r。 间l到r区间上的所以数变成近期的斐波那契数,相等的话取向下取。

解题思路:线段树。对于每一个节点新增一个bool表示该节点下面的位置是否都是斐波那契数。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>

#define lson(x) ((x<<1))
#define rson(x) ((x<<1)|1)

using namespace std;
typedef __int64 ll;

const int maxn = 100005;
const int maxf = 100;
const ll INF = 2000000000000000LL;

int n, m;
ll fib[maxf], fn, num[maxn];

struct maxnode {
    int l, r;
    ll sum;
    bool isfib;

    void set (int l, int r, ll sum, bool isfib) {
        this->l = l;
        this->r = r;
        this->sum = sum;
        this->isfib = isfib;
    }
} node[4 * maxn];

void init () {
    fib[0] = fib[1] = 1;
    for (fn = 2;; fn++) {
        fib[fn] = fib[fn - 2] + fib[fn - 1];
        if (fib[fn] > INF)
            break;
    } 
}

void pushup(int x) {
    int l = lson(x), r = rson(x);

    node[x].isfib = (node[l].isfib && node[r].isfib);
    node[x].sum = node[l].sum + node[r].sum;;
}

void build(int l, int r, int x) {
    node[x].set(l, r, 0, false);

    if (l == r)
        return;

    int mid = (l + r) / 2;

    build(l, mid, lson(x));
    build(mid + 1, r, rson(x));
}

ll find (ll x) {
    int id;
    ll ans = INF;
    for (int i = 0; i < fn; i++) {
        ll k = (fib[i] > x ?

fib[i] - x : x - fib[i]); if (k < ans) { ans = k; id = i; } } return fib[id]; } void add (int k, ll v, int x) { if (node[x].l == k && node[x].r == k) { node[x].sum += v; node[x].isfib = (find(node[x].sum) == node[x].sum ? true : false); return; } int mid = (node[x].l + node[x].r) / 2; if (k <= mid) add(k, v, lson(x)); else if (k > mid) add(k, v, rson(x)); pushup(x); } void insert(int l, int r, int x) { if (node[x].isfib) return; if (node[x].l == node[x].r) { node[x].sum = find(node[x].sum); node[x].isfib = true; return; } int mid = (node[x].l + node[x].r) / 2; if (l <= mid) insert(l, r, lson(x)); if (r > mid) insert(l, r, rson(x)); pushup(x); } ll query(int l, int r, int x) { if (node[x].l >= l && node[x].r <= r) return node[x].sum; int mid = (node[x].l + node[x].r) / 2; ll ans = 0; if (l <= mid) ans += query(l, r, lson(x)); if (r > mid) ans += query(l, r, rson(x)); return ans; } int main() { init(); while (scanf("%d%d", &n, &m) == 2) { build(1, n, 1); int Q, a, b; ll v; while (m--) { scanf("%d", &Q); if (Q == 1) { scanf("%d%I64d", &a, &v); add(a, v, 1); } else if (Q == 2) { scanf("%d%d", &a, &b); printf("%I64d\n", query(a, b, 1)); } else { scanf("%d%d", &a, &b); insert(a, b, 1); } } } return 0; }


转载于:https://www.cnblogs.com/yxysuanfa/p/6732952.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,HDU1622是一道关于二叉的题目,要求读入一系列二叉的节点信息,输出它们的层序遍历结果。如果输入的二叉不完整或存在重复节点,则输出"not complete"。下面是Java的实现代码: ```java import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; public class Main { static class Node { int val; Node left, right; public Node(int val) { this.val = val; } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { String s = sc.nextLine(); if (s.isEmpty()) { continue; } String[] nodes = s.split("\\s+"); Node root = new Node(Integer.parseInt(nodes[0].substring(1))); Queue<Node> queue = new LinkedList<>(); queue.offer(root); boolean isComplete = true; for (int i = 1; i < nodes.length - 1; i += 2) { Node cur = queue.poll(); if (!nodes[i].equals("()")) { cur.left = new Node(Integer.parseInt(nodes[i].substring(1))); queue.offer(cur.left); } else { isComplete = false; } if (!nodes[i + 1].equals("()")) { cur.right = new Node(Integer.parseInt(nodes[i + 1].substring(0, nodes[i + 1].length() - 1))); queue.offer(cur.right); } else { isComplete = false; } } if (!isComplete) { System.out.println("not complete"); continue; } StringBuilder sb = new StringBuilder(); queue.offer(root); while (!queue.isEmpty()) { Node cur = queue.poll(); sb.append(cur.val).append(" "); if (cur.left != null) { queue.offer(cur.left); } if (cur.right != null) { queue.offer(cur.right); } } System.out.println(sb.toString().trim()); } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值