牛牛的凑数游戏 --- 题解

目录

牛牛的凑数游戏:

题目大意:

思路解析:

代码实现:


牛牛的凑数游戏:

题目大意:

牛牛的凑数游戏 --- 题解_第1张图片

牛牛的凑数游戏 --- 题解_第2张图片 

思路解析:

        我们可以很容易一个区间是否会存在1,那么我们想如果存在1,且有3个1,那我们一定可以组成 1,2,3,那么为出现的数为4,如果这个区间还有一个四,我们可以发现我们一定可以组成5,6,7,那我们如果这个区间还有 a个3,b个2,那我们发现我们一定可以组成 [1,3+4+3*a+2*b],这是因为任意一个数都可以表示为 n = 4 * k + m, 0<=m<=3,那我们假设组成的3+4+3*a+2*b == 17,那么下一次的数一定可以表示为 n = 17 * k + m ( 0<=m<=16)..... 这个问题就转化为了 计算[1,1]的和 记作 a, 计算[1,a+1]的和 记住b,计算[1,b+1]的和。。。一直迭代下去最后一定会因为某些数字的未出现而结束。

        那么问题变为了查询 [l,r]这个区间 里面数字属于 [L,R]这个范围的和为多少。这个可以使用主席树实现。

代码实现:

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MAXN = (int) 1e5 + 5;
    static int tot = 0;
    static int[] a = new int[MAXN];
    static int[] root = new int[MAXN];
    static Node[] t = new Node[MAXN * 32];
    static int ans = 0;
    static int INF = (int) 1e9 +100;


    public static void main(String[] args) {
        int n = f.nextInt(); int m = f.nextInt();
        t[0] = new Node();
        for (int i = 1; i <= n; i++) {
            a[i] = f.nextInt();
            root[i] = ins(root[i], root[i - 1], 1, INF, a[i]);
        }
        while (m > 0){
            int l = f.nextInt();
            int r = f.nextInt();
            long cur = 0, res = 0;
            do {
                cur = res + 1;
                res = qry(root[l - 1], root[r], 1, INF, 1, Math.min(cur, INF));
            }while (cur <= res);
            System.out.println(cur);
            m--;
        }

    }

    public static long qry(int s, int e, int l, int r, int L, long R){
        if (L <= l && R >= r) return t[e].sum - t[s].sum;
        long res = 0;
        int mid = (l + r) >> 1;
        if (L <= mid) res += qry(t[s].l, t[e].l, l, mid, L, R);
        if (R > mid) res += qry(t[s].r, t[e].r, mid+1, r, L, R);
        return res;
    }
    public static int ins(int p, int q, int l, int r, int x){
        p = ++tot;
        t[p] = new Node(t[q]);
        t[p].sum += x;
        if (l == r) return p;
        int mid = (l + r) >> 1;
        if (x <= mid) t[p].l = ins(t[p].l, t[q].l, l, mid, x);
        else t[p].r = ins(t[p].r, t[q].r, mid+1, r, x);
        return p;
    }


    static class Node{
        int l, r;
        long sum;

        public Node(Node node) {
            this.l = node.l;
            this.r = node.r;
            this.sum = node.sum;
        }
        public Node(){}
    }

    static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
    static Input f = new Input(System.in);
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    static class Input {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public Input(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public String nextLine() {
            String str = null;
            try {
                str = reader.readLine();
            } catch (IOException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
            return str;
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public Double nextDouble() {
            return Double.parseDouble(next());
        }

        public BigInteger nextBigInteger() {
            return new BigInteger(next());
        }
    }
}

你可能感兴趣的:(算法)