老夫聊发少年狂,碱金属,丢池塘。浮溶游响,激起千朵浪|

Yaosicheng124

园龄:1年2个月粉丝:8关注:11

逐月新星杯

B. 拓扑图计数

题目描述

给定一个排列 p,求有多少个 DAG 的最小字典序拓扑序为 p

思路

我们对于每个点 pi,考虑前面的点连到 pi 的方案数。如果 i 前面没有有大于 pi 的就随便选。而如果有,令其为 j,那么 j 之前的还是照样随便选,但 j 之后至少要选一条边(因为 j 之后的一定都小于 pj)。

空间复杂度 O(N),时间复杂度最优 O(N)(但由于我弱智了,所以我是 O(NlogN))。

思路

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 200001, MOD = 998244353;

int n, tr[MAXN], ans = 1;

void update(int p, int x) {
  for(; p <= n; tr[p] = max(tr[p], x), p += (p & -p)) {
  }
}

int Getmax(int p) {
  int Max = 0;
  for(; p; Max = max(Max, tr[p]), p -= (p & -p)) {
  }
  return Max;
}

int Pow(int a, int b) {
  int ret = 1;
  for(; b; a = 1ll * a * a % MOD, b >>= 1) {
    if(b & 1) {
      ret = 1ll * ret * a % MOD;
    }
  }
  return ret;
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n;
  for(int i = 1, x; i <= n; ++i) {
    cin >> x;
    int last = Getmax(n - x + 1);
    update(n - x + 1, i);
    ans = 1ll * ans * (!last ? Pow(2, i - 1) : 1ll * Pow(2, last - 1) * (Pow(2, i - last) - 1 + MOD) % MOD) % MOD;
  }
  cout << ans;
  return 0;
}

D. 括号子区间

题目描述

我们定义一个合法括号串为:

  • 空串是合法括号串。
  • S 是合法括号串,则 (S) 也是合法括号串。
  • S,T 是合法括号串,则 ST 也是合法括号串。

现在你要构造一个括号串 S 使得其满足尽可能多的以下条件:

  • S[li:ri] 是一个合法括号串。

求满足条件最大数量。

思路

我们考虑两个条件 [li,ri],[lj,rj] 是否能兼容,有三种情况:

  • [li,ri][lj,rj]=,那么可以兼容。
  • [li,ri][lj,rj]=[li,ri]\or[li,ri][lj,rj]=[lj,rj],由于题目保证了 rili+1 为偶数,所以也可以兼容。
  • 否则说明 [li,ri],[lj,rj] 相交,如果相交的长度为偶数那么可以兼容,否则不行。

由于相交且相交部分为奇数的情况一定满足其 li 奇偶性不同,所以一定是二分图。

最后跑一遍二分图最大匹配求出最大独立集即可。

空间复杂度 O(M2),时间复杂度 O(M2M)

代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 501;

int n, m, l[MAXN], r[MAXN], ans, pl[MAXN], pr[MAXN], dist[MAXN];
bool flag[MAXN], vis[MAXN];
vector<int> e[MAXN];

bool bfs() {
  fill(vis + 1, vis + m + 1, 0);
  fill(dist + 1, dist + m + 1, 0);
  queue<int> que;
  for(int i = 1; i <= m; ++i) {
    if(l[i] % 2 && !pl[i]) {
      que.push(i);
      dist[i] = 1;
    }
  }
  for(; !que.empty(); ) {
    int u = que.front();
    que.pop();
    for(int v : e[u]) {
      if(!pr[v]) {
        return 1;
      }
      if(!dist[pr[v]]) {
        dist[pr[v]] = dist[u] + 1;
        que.push(pr[v]);
      }
    }
  }
  return 0;
}

bool dfs(int u) {
  if(vis[u]) {
    return 0;
  }
  vis[u] = 1;
  for(int v : e[u]) {
    if(!pr[v] || (dist[pr[v]] == dist[u] + 1 && dfs(pr[v]))) {
      pl[u] = v, pr[v] = u;
      return 1;
    }
  }
  return 0;
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n >> m;
  for(int i = 1; i <= m; ++i) {
    cin >> l[i] >> r[i];
  }
  for(int i = 1; i <= m; ++i) {
    for(int j = i + 1; j <= m; ++j) {
      if((r[i] >= l[j] && r[i] < r[j] && l[i] < l[j] && (r[i] - l[j] + 1) % 2) || (r[j] >= l[i] && r[j] < r[i] && l[j] < l[i] && (r[j] - l[i] + 1) % 2)) {
        if(l[i] % 2) {
          e[i].emplace_back(j);
          flag[j] = 1;
        }else {
          e[j].emplace_back(i);
        }
      }
    }
  }
  for(; bfs(); ) {
    for(int i = 1; i <= m; ++i) {
      ans += (l[i] % 2 && !pl[i] && dfs(i));
    }
  }
  cout << m - ans;
  return 0;
}

本文作者:yaosicheng124

本文链接:https://www.cnblogs.com/yaosicheng124/p/18498243

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Yaosicheng124  阅读(5)  评论(0编辑  收藏  举报
  1. 1 Minecraft C418
Minecraft - C418
00:00 / 00:00
An audio error has occurred.

暂无歌词

加载中…

{{tag.name}}

{{tran.text}}{{tran.sub}}
无对应文字
有可能是
{{input}}
尚未录入,我来提交对应文字
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示