📜  门| GATE-CS-2005 |第 45 题(1)

📅  最后修改于: 2023-12-03 14:58:26.432000             🧑  作者: Mango

门 | GATE-CS-2005 |第 45 题

题目描述

有一个空间划分为n个闭区间,每个闭区间有一个开/关状态。给定这些闭区间的状态,并给出一些查询操作,每个操作都是查询区间[l,r]之间具有开状态的闭区间数量。

实现函数void query(bool state[], int n, int queries[][2], int m, int answers[]),它将闭区间的状态存储在名为state的bool数组中,查询操作保存在两列的二维矩阵queries中,m是行数。查询结果应该返回到名为answers的整数数组中。

函数签名
void query(bool state[], int n, int queries[][2], int m, int answers[])
输入
  • state[]:bool类型的数组。size为n,表示每个闭区间的开关状态。
    • 状态为开,为true
    • 状态为关,为false
  • n:表示闭区间的数量
  • queries[][2]:int类型的二维数组,size为m*2。表示m个查询操作。每行都有两个元素代表一个查询范围[l,r]。此处的查询包括左右界点。
  • m:int类型的变量,表示查询操作的数量
  • answers[]:int类型的数组,其大小为m,用于存储查询结果
输出

query函数将查询结果存储在名为answers的整数数组中。

示例

示例1:

state[] = {true, false, true, false}
n = 4
queries[][] = {{1, 4}, {2, 3}}
m = 2
answers[] = {2, 1}

示例2:

state[] = {true, true, false, true, false}
n = 5
queries[][] = {{2, 4}}
m = 1
answers[] = {1}
解题思路

题目中给定一个长度为n的bool数组state,以及m个查询操作,每个操作查询区间[l,r]内开状态的区间数量。为此,我们可以使用一个差分数组da暂存相邻区间状态的变化,最终得到这些变化的前缀和,以便快速回答每个查询。

diff数组的i个元素da[i]表示从第i个区间到第i + 1个区间的状态变化。具体而言,如果第i个区间和第i + 1个区间的状态不同,则da[i]为1或-1,表示第i个区间的状态变化。否则,da[i]为0,即没有变化。

然后,我们对da数组进行前缀和处理得到数组ps,其中ps[i]表示从第1个区间到第i个区间的开状态区间数量。现在,对于给定的查询操作[ l,r],我们可以计算ps[r] - ps[l-1],即[1,r]内开状态的区间数目减去[1,l -1]内开状态的区间数目。该差异是所需的值。

void query(bool state[], int n, int queries[][2], int m, int answers[]) {
    int da[n];
    da[0] = state[0] ? 1 : -1;
    for (int i = 1; i < n; i++) {
        da[i] = state[i] != state[i - 1] ? state[i] ? 1 : -1 : 0;
    }
    int ps[n];
    ps[0] = da[0];
    for (int i = 1; i < n; i++) {
        ps[i] = ps[i - 1] + da[i];
    }
    for (int i = 0; i < m; i++) {
        int l = queries[i][0] - 1;
        int r = queries[i][1] - 1;
        answers[i] = l == 0 ? ps[r] : ps[r] - ps[l - 1];
    }
}

由于此算法的时间复杂度是O(n + m),它比对n个查询执行n个$O(n)$查找操作的总时间复杂度O(n^2)更有效率。