zoukankan      html  css  js  c++  java
  • ICPC昆明区域赛·赛前挣扎复习题

    HihoCoder - 1629 Graph (回滚莫队+并查集按秩合并)

    题目:https://vjudge.net/contest/419697#problem/C

    遇到了回滚莫队。

    https://blog.csdn.net/a54665sdgf/article/details/82501086

    开拓了眼界。

    并查集随机删除是不行的,但是可以按顺序撤销,回滚莫队恰好可以支持这种操作。

    [hihocoder 1635] Colored Nodes(思维+基环树)

    https://blog.csdn.net/alan_cty/article/details/78713865

    发现,虽然一轮之后,每个点的颜色不知道,但是知道这个点的颜色是从哪个点继承的

    然后继承关系是一个基环树

    只有环上的颜色最后F[i]值不为0

    且环上每个颜色最后答案一样。

    然后做一下就行

    关键在于发现:颜色不知道,但是知道这个点的颜色是从哪个点继承的,然后转化为基环树问题。

     

     

    D - Rikka with Subsequences

     

     https://blog.csdn.net/wxh010910/article/details/84950709

     (全网仅有的wxh的题解。。。。)

    cnt^3怎么处理?

    套路:用组合意义拆开。

    问题转化成为,三个相同的串,从每个串中分别选出一个子序列,这三个子序列相同的方案数。(方案不一样,当且仅当存在从某个串中选出来的子序列的位置不一样)

    但是还是很不好写。。。因为涉及到邻接矩阵的限制的问题。

    (此处省略理解代码1.5h)

    统计i,j,k位置结尾的合法子序列,必须要考虑上一个是不是能接上去,但是复杂度太高不能再枚举了。

    所以先固定i,就知道了a[i],也就是b[j],c[k]必须等于a[i],否则没有意义。

    很自然地设sum[j][k]表示,所有a中选<i的,b中选<j的,c中选<k的,且能直接拼在a[i]后面的三个位置作为结尾的合法子序列的方案数(显然这三个位置的字符相同)。

    到了一个新的i,那么sum就必须全部重新维护(因为a[i]变了),

    而sum[j][k]必然包含了从第二个串选1,2,...j-1的,第三个串选1,2,...,k-1位置的,按照二维前缀和的思想,sum[j][k]=sum[j-1][k]+sum[j][k-1]-sum[j-1][k-1]+val

    考虑val是什么

    就是以所有(<i,j-1,k-1)结尾的且能拼到i后面的子序列的方案数(要保证三个位置字符相同)

    设这个东西为dp[j][k](i维省了),那么dp[j][k]可以在之前几轮i的时候,枚举到a[i]==b[j]==c[k]的(i,j,k)的时候更新到

    只要我们先更新sum,再求i层的贡献,再更新dp[j][k]就行了。

    代码(from:wxh)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 234;
    const int md = 1e9 + 7;
    
    int n, a[N], dp[N][N], sum[N][N];
    char board[N][N];
    
    inline void add(int &x, int y) {
      x += y;
      if (x >= md) {
        x -= md;
      }
    }
    
    inline void sub(int &x, int y) {
      x -= y;
      if (x < 0) {
        x += md;
      }
    }
    
    int main() {
      int tt;
      scanf("%d", &tt);
      while (tt--) {
        scanf("%d", &n);
        for (int i = 0; i < n; ++i) {
          scanf("%d", &a[i]);
          --a[i];
        }
        for (int i = 0; i < n; ++i) {
          scanf("%s", board[i]);
        }
        for (int i = 0; i < n; ++i) {
          for (int j = 0; j < n; ++j) {
            dp[i][j] = 0;
          }
        }
        int answer = 0;
        for (int i = 0; i < n; ++i) {
          for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
              sum[j + 1][k + 1] = board[a[j]][a[i]] == '1' ? dp[j][k] : 0;
              add(sum[j + 1][k + 1], sum[j + 1][k]);
              add(sum[j + 1][k + 1], sum[j][k + 1]);
              sub(sum[j + 1][k + 1], sum[j][k]);
            }
          }
          for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
              if (a[i] == a[j] && a[i] == a[k]) {
                int ways = 1;
                add(ways, sum[j][k]);
                add(answer, ways);
                add(dp[j][k], ways);
              }
            }
          }
        }
        printf("%d
    ", answer);
      }
      return 0;
    }
    View Code

    总结:

    1.组合意义拆分次方

    2.注意固定i以后,得到更多的条件以简化复杂度,比如这里sum就额外赋予了新的要求:子序列能接在i的后面。这个sum用平行的循环更新就行。

    3.思路:组合意义转化->sum设出来->再维护dp->处理好先后顺序

    C - Vasya and Robot

    https://vjudge.net/contest/429333#problem/C

    思路别想太复杂=。=

    考虑选出一个区间行不行,发现只要考虑区间外面U,D,L,R个数就行了

    然后发现可以二分。没了。

    (其实有单调性可以只扫一遍,固定右端点,左端点往左走,直到成为合法区间,再往左移动右端点,左端点也不用回撤)

    D - Berland Fair

     https://vjudge.net/contest/429333#problem/D

    可以直接用线段树模拟。

    注意,pushdown的标记也要下放给子区间!!!

    pym的方法:

    重复:

    1.能完整绕圈就绕圈。(取模)

    2.否则,从1出发暴力走一圈,模拟这一圈的过程。绕完以后,删除a[i]>T的i(用个堆删),维护剩下a[i]的和(便于1操作绕圈)

    直到T变为0或者删完

    复杂度:

    每次绕圈会让T至少减半。

    否则如果不能绕圈,那么暴力走一遍,如果走了一遍没有使T减半,那么意味着真正做出贡献的a[i]的和(设为S)很小,而其他没有做出贡献的a[i]就再也不能走了。

    这样的话,S<<T,那么下次一定可以绕圈。所以还是能让T减半

    很好写。

    算是一种绕圈取模题的思路,考虑让规模减半,使得暴力次数不多。

  • 相关阅读:
    Algorithms
    Algorithms
    再探循环神经网络
    循环神经网络(RNN)
    AI:深度学习用于文本处理
    人们怎么使用 AI 抵抗冠状病毒
    AI:拿来主义——预训练网络(二)
    AI:拿来主义——预训练网络(一)
    AI:是猫还是狗,这是个问题
    Android Studio 3.6 正式版终于发布了
  • 原文地址:https://www.cnblogs.com/Miracevin/p/14566392.html
Copyright © 2011-2022 走看看