<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Codeforces Round 1051 (Div. 2) D1D2題解

      D1. Inversion Graph Coloring (Easy Version)

      題意:

      給定一個序列 \(a_1, a_2, \ldots, a_n\),我們需要計算其“好”子序列的數量。一個子序列是“好”的,如果存在一種將它的索引染成紅色或藍色的方式,使得對于任何一對索引 \(i < j\) 且子序列中 \(b_i > b_j\),索引 \(i\)\(j\) 的顏色不同。換句話說,子序列的逆序圖是二分圖。

      思路:

      經分析,一個子序列是“好”的當且僅當它不包含長度為 3 的遞減子序列(即沒有三個元素 \(b_i > b_j > b_k\)\(i < j < k\))。因此,問題轉化為計算序列中所有不包含長度為 3 的遞減子序列的子序列的數量

      由于 $n \leq 300 $ 且所有測試用例的 $ n $ 總和不超過 300,我們可以使用動態規劃(DP)來高效計數。

      DP 狀態設計

      定義 DP 狀態 ( dp[j][k] ) 表示當前子序列的最大值為 ( j )、次大值為 ( k ) 的子序列數量。其中 ( j ) 和 ( k ) 是序列中的值(范圍從 0 到 ( n ),0 用于表示空狀態)。初始狀態 ( dp[0][0] = 1 ) 代表空子序列。

      狀態轉移

      遍歷序列中的每個元素$ ( a_i )$ 時,對于每個狀態 \((j, k)\) ,我們考慮兩種選擇:

      1. 不選當前元素:狀態不變,即 $ dp[j][k] $ 貢獻到新狀態 $ cp[j][k]$。
      2. 選當前元素:根據 $ a_i $ 與當前最大值 $ j $ 和次大值 $ k $ 的關系更新狀態:
        • 如果 \(( a_i \geq j )\),添加后新最大值為 ( a_i ),次大值為 ( j ),狀態轉移到 ( cp[a_i][j] )。
        • 如果 \(( a_i < j )\)\(( a_i \geq k )\),添加后最大值不變,次大值更新為 \(( a_i )\),狀態轉移到 \(( cp[j][a_i] )\)
        • 如果 \(( a_i < k )\),添加后會形成三個遞減元素 \(( j > k > a_i )\),因此不能選,跳過。

      這樣確保所有計數的子序列都不包含長度為 3 的遞減子序列。

      代碼

      #include<bits/stdc++.h>
      #define ll long long
      #define ce cerr
      #define ull unsigned long long
      #define lll __int128
      #define PII pair<int, int>
      #define PLL pair<long ,long>
      #define int long long
      using namespace std;
      
      const int inf = 0x3f3f3f3f;
      const ll iinf = 1e18;
      const int N = 310;
      const int mod = 1e9 + 7;
      
      int t;
      
      void solve() {
          int n;
          cin >> n;
          vector<int> a(n + 1);
          for (int i = 0; i < n; ++i) {
              cin >> a[i];
          }
          // dp[j][k] 表示當前子序列的最大值為 j,次大值為 k 的子序列數量
          vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));
          dp[0][0] = 1; // 初始狀態:空子序列
          for (int i = 0; i < n; ++i) {
              vector<vector<int>> cp(n + 1, vector<int>(n + 1, 0)); // 臨時狀態矩陣
              for (int j = 0; j <= n; ++j) {
                  for (int k = 0; k <= n; ++k) {
                      // 不選當前元素 a[i]
                      cp[j][k] = (cp[j][k] + dp[j][k]) % mod;
                      // 選當前元素 a[i]
                      if (a[i] >= j) {
                          // 新最大值是 a[i],次大值是 j
                          cp[a[i]][j] = (cp[a[i]][j] + dp[j][k]) % mod;
                      } else if (a[i] >= k) {
                          // 最大值不變,次大值更新為 a[i]
                          cp[j][a[i]] = (cp[j][a[i]] + dp[j][k]) % mod;
                      } else {
                          // 如果 a[i] < k,添加會形成三個遞減,跳過
                          continue;
                      }
                  }
              }
              dp = cp; // 更新狀態
          }
          ll res = 0;
          // 求和所有狀態的值
          for (int i = 0; i <= n; ++i) {
              for (int j = 0; j <= n; ++j) {
                  res = (res + dp[i][j]) % mod;
              }
          }
          cout << res << "\n";
      }
      
      signed main() {
          ios::sync_with_stdio(false);
          cin.tie(NULL);
          cout.tie(NULL);
          t = 1;
          cin >> t;
          while (t--) {
              solve();
          }
          return 0;
      }
      

      D2. Inversion Graph Coloring (Hard Version)

      題意:

      同前,でも\(n = 2000\)

      思路:

      \(dp[j][k]\) 表示:已經選的子序列中兩種顏色各自最后一個元素的值(分別記為 \(j\)\(k\))。
      遍歷新元素 \(v = a[i]\) 時,只會修改兩類位置:行 \(\boxed{j == v}\) (把元素放到顏色1)和列 \(\boxed{k == v}\) (把元素放到顏色2,且 \(j > v\))。因此不必在每一步重建整個 \(n \times n\) 表格,只需要對這兩類位置做增量更新。
      對于行更新需要按列查詢列前綴和:\(\sum_{j=0}^{v} dp[j][k]\),為此給每一列維護一個 Fenwick(按 \(j\) 的維度做前綴和)。
      對于列更新需要按行查詢行前綴和:\(\sum_{k=0}^{v} dp[j][k]\),為此給每一行維護一個 Fenwick(按 \(k\) 的維度做前綴和)。
      每次把增量寫回 \(dp\) 的同時,立刻更新對應的行/列 Fenwick(因為這些增量只會影響未來元素的查詢,但對本次同一列/同行的查詢順序不會產生交叉影響,按上面順序逐項處理即可安全使用)。

      代碼

      #include<bits/stdc++.h>
      #define ll long long
      #define ce cerr
      #define ull unsigned long long
      #define lll __int128
      #define PII pair<int, int>
      #define PLL pair<long ,long>
      #define int long long
      using namespace std;
       
      const int inf = 0x3f3f3f3f;
      const ll iinf = 1e18;
      const int N = 310;
      const int MOD = 1e9 + 7;
      //cin.ignore(std::numeric_limits< streamsize >::max(), '\n');
      int t;
      //dp[i][j]
      struct Fenwick {
          int n; 
          vector<int> bit;
          Fenwick() : n(0) {}
          Fenwick(int _n) { init(_n); }
          void init(int _n) {
              n = _n; // we will use positions 0..(n-1) if _n is count
              bit.assign(n + 5, 0);
          }
          // add val to position pos (pos in [0..n-1])
          void add(int pos, int val) {
              if (val == 0) return;
              int i = pos + 1;
              while (i <= n) {
                  bit[i] += val;
                  if (bit[i] >= MOD) bit[i] -= MOD;
                  i += i & -i;
              }
          }
          // sum of [0..pos], pos in [-1..n-1]
          int sumPrefix(int pos) {
              if (pos < 0) return 0;
              int i = pos + 1;
              int res = 0;
              while (i > 0) {
                  res += bit[i];
                  if (res >= MOD) res -= MOD;
                  i -= i & -i;
              }
              return res;
          }
      };
      void solve() {
           int n;
           cin >> n;
           vector<int> a (n + 1);
           for (int i = 0; i < n; ++i) {
               cin >> a[i];
           }
           // dp[j][k], j,k in [0..n]
           vector<vector<int> > dp (n + 1, vector<int> (n + 1, 0));   
           dp[0][0] = 1;
           // vec1 = rowFen[j] (for fixed j, prefix over k)
           // vec2 = colFen[k] (for fixed k, prefix over j)
           vector<Fenwick> vec1 (n + 1), vec2 (n + 1);
           for (int i = 0; i <= n; ++i) {
               vec1[i].init(n + 1);
               vec2[i].init(n + 1);
           }
           // initial state
           vec1[0].add(0, 1);
           vec2[0].add(0, 1);
      
           for (int idx = 0; idx < n; ++idx) {
               int v = a[idx]; // 1..n
      
               // 1) 把當前元素放到“顏色1”的末尾 -> 更新行 j == v:
               // 對每個 k in [0..n]: dp[v][k] += sum_{j=0..v} dp[j][k]  (colFen[k].sumPrefix(v))
               for (int k = 0; k <= n; ++k) {
                   int addVal = vec2[k].sumPrefix(v);
                   if (addVal == 0) continue;
                   dp[v][k] += addVal;
                   if (dp[v][k] >= MOD) dp[v][k] -= MOD;
                   vec1[v].add(k, addVal);   // 更新 rowFen[v] 的 k 位置
                   vec2[k].add(v, addVal);   // 更新 colFen[k] 的 j=v 位置
               }
      
               // 2) 把當前元素放到“顏色2”的末尾 -> 更新列 k == v,但只有 j > v 才走這條
               // 對每個 j in (v..n]: dp[j][v] += sum_{k=0..v} dp[j][k] (rowFen[j].sumPrefix(v))
               for (int j = v + 1; j <= n; ++j) {
                   int addVal = vec1[j].sumPrefix(v);
                   if (addVal == 0) continue;
                   dp[j][v] += addVal;
                   if (dp[j][v] >= MOD) dp[j][v] -= MOD;
                   vec1[j].add(v, addVal);
                   vec2[v].add(j, addVal);
               }
           }
           ll res = 0;
           for (int i = 0; i <= n; ++i) {
               for (int j = 0; j <= n; ++j) {
                   res = (res + dp[i][j]) % MOD;
               }
           }
           cout << res << "\n";
      }
      signed main() {
           ios::sync_with_stdio (false);
           cin.tie(NULL);
           cout.tie(NULL);
           t = 1;
           cin >> t;
           while (t --) {
               solve();
           }
           return 0;
      }
      
      
      posted @ 2025-09-22 18:49  Li_Yujia  閱讀(47)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 午夜丰满少妇性开放视频| 欧美亚洲综合成人a∨在线| 亚洲综合一区国产精品| 中文字幕亚洲男人的天堂| 亚洲爆乳少妇无码激情| 亚洲精品一区二区麻豆| 国产熟女精品一区二区三区| 久久国产精品老女人| 婷婷六月综合缴情在线| 久久久精品波多野结衣av| 国产精品十八禁在线观看| 99久久精品久久久久久清纯| 亚洲精品漫画一二三区| 亚洲精品综合网中文字幕| 三人成全免费观看电视剧高清| 99久久亚洲综合精品网| 欧产日产国产精品精品| 国产互换人妻xxxx69| 国产成人8X人网站视频| 最近中文字幕完整版| 久久久久综合中文字幕| 在线 欧美 中文 亚洲 精品| 国产精品黄色精品黄色大片| 男女激情一区二区三区| 国产精品无码mv在线观看| 人妻人人澡人人添人人爽| 亚洲精品国产综合久久一线| 亚洲中文无码av永久不收费| 免费午夜无码片在线观看影院 | 91精品一区二区蜜桃| 国产精品日日摸夜夜添夜夜添2021| 亚洲人成人日韩中文字幕| 国产婷婷综合在线视频| 久久国产精品第一区二区| 国产高清免费午夜在线视频| 成人免费在线播放av| 日韩有码中文字幕第一页| 丰满爆乳一区二区三区| 免费的特黄特色大片| 91精品国产91热久久久久福利| 亚洲aⅴ男人的天堂在线观看 |