ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF380C Sereja and Brackets 题解 数列分块

2022-07-14 08:35:43  阅读:157  来源: 互联网

标签:cnt log CF380C int 题解 Brackets bl maxn vec


题目链接:https://codeforces.com/contest/380/problem/C

题目大意:给定长度为 \(n(\le 10^6)\) 的一个括号序列,有 \(m(\le 10^5)\) 次询问,每次询问给定一个区间 \([l,r]\),你需要回答出区间 \([l,r]\) 范围内的所有子序列里面最长的合法括号表达式的长度。

解题思路:

首先,无论在哪个区间范围内,每一个 ')' 所匹配的 '(' 都是固定的。

我们可以用 \(f[i]\) 表示下标为 \(i\) 的 ')' 所匹配的 '(' 对应的下标。

对于每次询问的 \(l\) 和 \(r\),问题就变成了询问区间 \([l,r]\) 范围内存在多少 \(f[i]\) 满足 \(f[i] \ge l\)。

这个问题用 分块 是很好解决的,对于完整的分开,只需要初始时对每个分块的 \(f[i]\) 排序,然后查询的时候就可以二分查找 \(\le l\) 的元素个数。

时间复杂度是 \(O(m \cdot \sqrt{n} \cdot \log n)\),但是因为常数比较小(这里的 \(\log n\) 其实是 \(\log \sqrt{n} = \frac{1}{2} \log n\),然后不匹配的状态 \(f[i]\) 也不用保存),所以能够解决这个问题。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
char s[maxn];
int n, m, l, r, f[maxn];
int blo, bl[maxn];
vector<int> vec[1010];

void init() {
    stack<int> stk;
    for (int i = 1; i <= n; i++) {
        if (s[i] == '(') stk.push(i);
        else if (!stk.empty()) {
            f[i] = stk.top();
            stk.pop();
        }
    }
    blo = sqrt(n);
    for (int i = 1; i <= n; i++) {
        bl[i] = (i - 1) / blo + 1;
        if (f[i]) vec[bl[i]].push_back(f[i]);
    }
    for (int i = 1; i <= bl[n]; i++)
        sort(vec[i].begin(), vec[i].end());
}

int solve(int l, int r) {
    int cnt = 0;
    for (int i = l; i <= min(bl[l]*blo, r); i++) if (f[i] >= l) cnt++;
    if (bl[l] != bl[r]) {
        for (int i = (bl[r]-1)*blo+1; i <= r; i++) if (f[i] >= l) cnt++;
    }
    for (int i = bl[l]+1; i < bl[r]; i++) {
        int num = vec[i].end() - lower_bound(vec[i].begin(), vec[i].end(), l);
        cnt += num;
    }
    return cnt * 2;
}

int main() {
    scanf("%s%d", s+1, &m);
    n = strlen(s+1);
    init();
    while (m--) {
        scanf("%d%d", &l, &r);
        printf("%d\n", solve(l, r));
    }
    return 0;
}

标签:cnt,log,CF380C,int,题解,Brackets,bl,maxn,vec
来源: https://www.cnblogs.com/quanjun/p/16476218.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有