codeforces 解题报告 978C. Letters binary search

http://codeforces.com/contest/978/problem/C

解题思路:

1.数据范围比较大,暴力复杂度大概O(n*n),爆搜一定超时

2.由于宿舍是连续的,房间也是连续的,所以我们假设所有房间呈递增分布(1 ~ a1+a2+……+an)

3.按照宿舍楼进行统计分布的话会得到一条序列,表示楼内宿舍的最大房间号,通过与前一栋楼的最大房间号进行计算得到任意的房间号

4.例如样例1,根据宿舍房间数(10,15,12)得到的新序列为(10,25,37),然后为了计算方便我假设有编号为0的宿舍楼,并设置房间数为0,即新序列为(0,10,25,37),下标编号为(0,1,2,3)

5.每一个查询,我们二分新序列得到对应的宿舍楼下标编号,打印;然后通过查询值减得到的下标的前一栋楼的最大房间编号得到在该栋楼的房间原编号( check - new[tag - 1] ),打印结果。这样就顺利把复杂度降为了O(mlogn)

import java.util.Scanner; 
import java.util.Vector;

public class Main {

    //计算公式:tag为宿舍楼编号,goal-ve[tag]表示楼内的房间编号
    //把宿舍房间弄成递增线性,方便二分
    static Vector<Long> ve = new Vector<>();
    //二分宿舍找到大于等于查找值得宿舍下标
    static int upperBound(int left,int right,long goal) {

        int mid = (left + right) >> 1;
        if(ve.get(mid) == goal || (ve.get(mid) > goal && ve.get(mid - 1) < goal)) {
            return mid;
        } else if(ve.get(mid) > goal) {
            return upperBound(left,mid,goal);
        } else if(ve.get(mid) < goal) {
            return upperBound(mid + 1,right,goal);
        }
        return 0;
    }

    public static void main(String args[]) {

        ve.add(0, (long) 0);
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(),m = sc.nextInt();
        for(int i = 1;i <= n;i++) {
            long x = sc.nextLong();
            ve.add(i,x + ve.get(i - 1));
        }

        for(int i = 1;i <= m;i++) {
            long x = sc.nextLong();
            int tag = upperBound(1,n,x);
            System.out.println(tag + " " + (x - ve.get(tag - 1)));
        }
    }
}

猜你喜欢

转载自blog.csdn.net/a912952381/article/details/81063008