zoukankan      html  css  js  c++  java
  • HDU

    HDU - 5357

    有很显然的 nlogn 的写法, 但是肯定过不了。。

    感觉很巧妙的一道题, 充分利用了性质。

    match[ i ]  表示和 i 匹配的是谁

    a[ i ] 表示从 i 开始往后有多少个合法段。

    b[ i ] 表示从 j 开始往前有多少个合法段。

    up[ i ] 表示真包含 i,  match[ i ] 的最小匹配括号的(的下标

    ans[ i ] = ans[ up[ i ] ] + a[ i ] * b[ match[ i ] ]

    //#pragma GCC optimize(2)
    //#pragma GCC optimize(3)
    //#pragma GCC optimize(4)
    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 1e6 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T &a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T &a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;}
    
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    
    int n;
    int stk[N], top;
    int match[N], a[N], b[N], up[N];
    int ans[N];
    char s[N];
    
    void init() {
        for(int i = 1; i <= n + 5; i++) {
            match[i] = 0;
            a[i] = 0;
            b[i] = 0;
            up[i] = 0;
            ans[i] = 0;
        }
    }
    
    int main() {
        int T; scanf("%d", &T);
        while(T--) {
            scanf("%s", s + 1);
            n = strlen(s + 1);
            init();
    
            top = 0;
            for(int i = 1; i <= n; i++) {
                if(s[i] == '(') {
                    up[i] = stk[top];
                    stk[++top] = i;
                }
                else if(top) {
                    match[i] = stk[top];
                    match[stk[top]] = i;
                    top--;
                }
            }
    
            for(int i = 1; i <= n; i++) {
                if(!match[i] || s[i] == '(') continue;
                b[i] = b[match[i] - 1] + 1;
            }
    
            for(int i = n; i >= 1; i--) {
                if(!match[i] || s[i] == ')') continue;
                a[i] = a[match[i] + 1] + 1;
            }
    
            for(int i = 1; i <= n; i++) {
                if(!match[i] || s[i] == ')') continue;
                ans[i] = 1LL * a[i] * b[match[i]] % mod;
                if(up[i]) add(ans[i], ans[up[i]]);
                ans[match[i]] = ans[i];
            }
    
            LL ret = 0;
            for(int i = 1; i <= n; i++) {
                ret += 1LL * ans[i] * i % mod;
            }
    
            printf("%lld
    ", ret);
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    变量的创建和初始化
    HDU 1114 Piggy-Bank (dp)
    HDU 1421 搬寝室 (dp)
    HDU 2059 龟兔赛跑 (dp)
    HDU 2571 命运 (dp)
    HDU 1574 RP问题 (dp)
    HDU 2577 How to Type (字符串处理)
    HDU 1422 重温世界杯 (dp)
    HDU 2191 珍惜现在,感恩生活 (dp)
    HH实习 acm算法部 1689
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11217179.html
Copyright © 2011-2022 走看看