題目整理3

  • CF785D

計數
http://codeforces.com/contest/785/problem/D

題解

  1. 非常有意思的一道題,求一段括號序列中RSBS的個數,但有個關鍵點必須事先知道不然無法做。
  2. 對于前x個為左括號后y個為右括號的序列,它的RSBS為( x x+y
  1. 若指定某個左括號為RSBS序列最后的左括號,他在原序列中前面有x-1個左括號,后面有y個右括號,則這樣的RSBS序列有(xx+y-1)個。
  2. 詳情見http://codeforces.com/blog/entry/50996
  3. 1到n n個數的逆元可以O(n)求, 通過(b<sup >a)可以O(1)求(b+1a+1)和(ba-1), 綜上復雜度為O(n);

代碼

#include<cstdio>
typedef long long ll;
const int MAXN = 2e5+1e3;
const int MOD = 1e9+7;
ll ans = 0, cur;
ll inv[MAXN];
char s[MAXN];
int n, x, y, a;
int main() {
    scanf("%s", s);
    inv[0] = 0;
    inv[1] = 1;
    for(int i=2; i<MAXN; ++i)
        inv[i] = -inv[MOD%i]*(MOD/i)%MOD;
    x = y = n = 0;
    for(char *p=s; *p; ++p) {
        if(*p==')') ++y;
        ++n;
    }
    a = x+y-1;
    cur = 1;
    for(int i=0; i<n&&y; ++i) {
        if(s[i]=='(') {
            ++a, ++x;
            cur = cur*a%MOD*inv[x]%MOD;
            ans = (ans+cur)%MOD;
        }
        else {
            cur = cur*(a-x)%MOD*inv[a]%MOD;
            --a, --y;
            if(!y) break;
        }
    }
    if(ans<0) ans+=MOD;
    printf("%I64d\n", ans);
    return 0;
}
  • topcoder SRM 710 div2 C

圖論最大最小
Problem Statement

You are given an undirected graph with n nodes and m edges. The nodes are labeled from 0 to n-1. This graph is guaranteed to be connected and have no self-loops or multiple edges.
You are given a description of the graph: the vector <int>s a, b, w, and v. For each valid i, there is an edge that connects nodes a[i] and b[i] and has weight w[i]. For each valid j, node j has weight v[j]. All weights are positive integers.
A path in this graph is a sequence of pairwise distinct nodes such that each pair of consecutive nodes is connected by an edge. The difficulty of a path is the value (N times E), where N is the maximum weight of a node on the path (including the nodes where it starts and ends) and E is the maximum weight of an edge on the path.
For each pair of distinct nodes i and j, let d(i,j) be the smallest possible difficulty of a path that connects i and j. Find and return the sum of d(i,j) with 0 ≤ i < j ≤ n-1.

題解:

有幾點
1.  最大的點值最小的路徑不一定與最大邊值最小的路徑相同
2.  a到b有多條路徑, b到c有1條路,a到b的最優解不一定被包含在a到c的最優解。
3.  一個解法為,枚舉每個點,假設他為路徑上點值最大的點,找到點值小于等于他的點,包含他所構成的連通分量,在進行算,復雜度O(n^4).

代碼:

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 312;
typedef pair<int,int> pii;
int dbg = 0;
class MinMaxMax
{
    long long d[MAXN][MAXN];
    int fa[MAXN];
    bool alive[MAXN];
    vector<pii> su, se;
    vector<int> sa, sb;
    int n, m;
public: 
    int getfa(int x) {
        if(x==fa[x]) return x;
        return fa[x]=getfa(fa[x]);
    }
    long long findMin(vector <int> a, 
            vector <int> b, 
            vector <int> w, 
            vector <int> v) {
        m = a.size();
        n = v.size();
        su.clear();
        se.clear();
        int i, j;
        i=0; for(auto e: w)
            se.push_back(make_pair(e, i++));
        i=0; for(auto u: v)
            su.push_back(make_pair(u, i++));
        sort(su.begin(), su.end());
        sort(se.begin(), se.end());
        memset(d, 0x3f, sizeof(d));
        for(auto u:su) {
            for(i=0; i<n; ++i) fa[i] = i;
            for(auto ui:su)
                alive[ui.second] = (ui.first<=u.first);
            for(auto e:se) {
                int s=a[e.second], t=b[e.second];
                if(!alive[s]||!alive[t]) continue;
                s=getfa(s); t=getfa(t);
                if(s==t) continue;
                sa.clear(); sb.clear();
                for(i=0; i<=n; ++i) {
                    if(getfa(i)==s) sa.push_back(i);
                    else if(getfa(i)==t) sb.push_back(i);
                }
                long long cur = 1ll*e.first*u.first;
                for(auto ai:sa)
                    for(auto bi:sb) {
                        d[ai][bi] = min(d[ai][bi], cur);
                        d[bi][ai] = min(d[bi][ai], cur);
                    }
                fa[s] = fa[t] = min(s,t);
            }
        }
        long long ret = 0;
        for(i=0; i<n; ++i)
            for(j=i+1; j<n; ++j)
                ret += d[i][j];
        return ret;
    }
};

FZU-2128

AC自動機
https://vjudge.net/problem/FZU-2128
題解: 上個月做的一道AC自動機的模板題,主要是做個整理

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int MAXL = 1<<20;
const int MAXN = 1e5+1e3;
char s[MAXL];
vector<pair<int,int> > v;
struct Trie{
    int ch[MAXN][26];
    int val[MAXN], sz;
    int last[MAXN], f[MAXN];
    void clear() {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
    }
    int idx(char c) {
        return c-'a';
    } 
    void insert(char* s) {
        int u = 0, i;
        for(i=0; s[i]; ++i) {
            int c= idx(s[i]);
            if(!ch[u][c]) {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = i;
    }
    void print(int ed, int j) {
        if(j) {
            v.push_back(make_pair(ed-val[j]+1, ed));
            print(ed, last[j]);
        }
    } 
    void find(char* T) {
        int l = strlen(T);
        int j = 0;
        for(int i=0; i<l; ++i) {
            int c = idx(T[i]);
            while(j&&!ch[j][c]) j=f[j];
            j = ch[j][c];

            if(val[j]) print(i,j);
            else if(last[j]) print(i, last[j]);
        }   
    }
    void getFail() {
        queue<int> q;
        f[0] = 0;
        for(int c=0; c<26; ++c) {
            int u = ch[0][c];
            if(u) {
                f[u] = last[u] = 0;
                q.push(u);
            }
        }
        while(!q.empty()) {
            int r = q.front(); q.pop();
            for(int c=0; c<26; ++c) {
                int u = ch[r][c];
                if(!u) continue;
                q.push(u);
                int v = f[r];
                while(v&&!ch[v][c]) v=f[v];
                f[u] = ch[v][c];
                last[u] = val[f[u]]?f[u]:last[f[u]];
            }
        }
    }
}AC;
int main() {
    ios::sync_with_stdio(false);
    while(cin >> s) {
        char tmp[128];
        int n, len;
        len = strlen(s);
        cin >> n;
        AC.clear();
        for(int i=0; i<n; ++i) {
            cin >> tmp;
            AC.insert(tmp);
        }
        AC.getFail();
        v.clear();
        AC.find(s);
        sort(v.begin(), v.end());
        int l = 0, ans=0;
        for(int i=0; i<v.size(); ++i) {
            ans = max(ans,v[i].second-l);
            l = v[i].first+1;
        }
        ans = max(ans, len-l);
        cout << ans << endl;
    }
    return 0;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一位朋友曾這么感嘆自己的媽媽:她最不值得了,一生為子女操勞,卻吃力不討好。到最后,連她自己都說,沒有人會喜歡她。 ...
    凌星虹閱讀 535評論 1 16
  • 早春的天氣,多大風。艷陽,天空澄藍,無云。傍晚時,開車經過老碼頭,被半邊天火紅的顏色吸引,那是一輪巨大的即將歸隱的...
    悠游四海閱讀 359評論 6 3