2022暑假牛客多校2(G/K/D)

G. Link with Monotonic Subsequence

总结:

  • 子串(substring):s.substring,连续的
  • 子序列(subsequence):不连续的
  • 从二元组至少为一半可得sqrt(n)

由于最多两个变量,而要让整个最小必定是均匀分布的,考虑1/2或sqrt(),由数字举例得应用sqrt()

#include
using namespace std;
int main() {
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        int m = ceil(sqrt(n));
        int now = m;
        int pre = 0;
        while(pre <= n){
            for (int i = now; i > pre; --i){
                cout << i << " ";
            }
            now = min(now + m, n);
            pre = min(pre + m, n + 1);
        }
        cout << endl;
    }
    return 0;
}

K. Link with Bracket Sequence I

总结:

  • 明显dp,变量为是否加入括号,所以应该选择一个括号为重点,对状态进行分析
  • 两个字串的匹配需要两维,是否合法还需要一维

dp[i][j][k] : 前i个里匹配了j个序列,多出了k个左括号(不合法)

当前为左括号:

  • 匹配长度不变 : dp[i - 1][j][k + 1] 不合法的左括号减少,这一位不管
  • 匹配长度增加 :dp[i - 1][j - 1][k - 1] 不合法的左括号增加,这一位为左括号

右括号同理,与左括号刚好相反

int dp[205][205][205];
int main() {
	IOS;
    int t;
    cin >> t;
    while(t--){
        re(dp);
        int n, m;
        cin >> n >> m;
        string s;
        cin >> s;
        s = " " + s;
        dp[0][0][0] = 1;
        for (int i = 1; i <= m; ++i){
            for (int j = 0; j <= i; ++j){
                for (int k = 0; k <= i; ++k){
                    if(j == 0){
                        if(k)
                            dp[i][0][k] += dp[i - 1][0][k - 1];
                        dp[i][0][k] += dp[i - 1][0][k + 1];
                    }
                    else if(s[j] == '('){
                        dp[i][j][k] += dp[i - 1][j][k + 1];
                        if(k)
                        dp[i][j][k] += dp[i - 1][j - 1][k - 1];
                    }
                    else {
                        if(k)
                            dp[i][j][k] += dp[i - 1][j][k - 1];
                        dp[i][j][k] += dp[i - 1][j - 1][k + 1];
                    }
                      dp[i][j][k]%=mod;
                }
            }
        }
        cout << dp[m][n][0] << endl;
    }
    return 0;
}

D. Link with Game Glitch

总结:

  • 拓扑排序:判断是否有环(不管正负), bf:判断负环
  • 无限循环可以考虑下是不是图
  • spfa并不是完全没用的,例如这道题判负环

2022暑假牛客多校2(G/K/D)_第1张图片

vector e[2010];
double dis[2010];
const int inf = 0x3f3f3f3f;
int cnt[2010];
bool vis[2010];
bool check(int n, double mid) {
    mid = log(mid);
    memset(dis, 0, sizeof(dis));
    re(cnt);
    queue q;
    for(int i = 1; i <= n; ++i){
        q.push(i);
        vis[i] = true;
    }
    while(!q.empty()){
        int temp = q.front();
        q.pop();
        vis[temp] = false;//反复出队入队
        for(auto w: e[temp]){
            if(dis[w.first] < dis[temp] + mid + w.second){
                dis[w.first] = dis[temp] + mid + w.second;
                cnt[w.first] = cnt[temp] + 1;
                if(cnt[w.first] > n)//有负环
                    return false;
                if(!vis[w.first]){
                    q.push(w.first);
                    vis[w.first] = true;
                }
            }
        }
    }
  return true;
}

int main() {
	int n, m;
    cin >> n >> m;
    int start = 0;
    for(int i = 0; i < m; ++i){
        int b, d;
        double a, c;
        cin >> a >> b >> c >> d;
        e[b].push_back({d, log(c / a)});
    }
    double l = 0, r = 1000;
    while((r - l) >= 1e-6){
            double mid = (l + r) / 2;
            if(check(n,mid))
                l = mid;
            else
                r = mid;
    }
    cout << l;
    return 0;
}

你可能感兴趣的:(c++,算法)