日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Codeforces Round #699 (Div. 2) 题解

發布時間:2023/12/3 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Codeforces Round #699 (Div. 2) 题解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • A. Space Navigation
  • B. New Colony
  • C. Fence Painting
  • D. AB Graph
  • E. Sorting Books
  • F. AB Tree

#699-Div.2

A. Space Navigation

對于最終位置(x,y),我們只關心那兩個方向的字符是否足夠即可

#include <cstdio> #include <cstring> #define maxn 100005 int T, n, m; char s[maxn];int main() {scanf( "%d", &T );while( T -- ) {scanf( "%d %d %s", &n, &m, s + 1 );char x = n < 0 ? 'L' : 'R';char y = m < 0 ? 'D' : 'U';int len = strlen( s + 1 );int cntx = 0, cnty = 0;for( int i = 1;i <= len;i ++ ) {if( s[i] == x ) cntx ++;if( s[i] == y ) cnty ++;}if( n < 0 ) n = -n;if( m < 0 ) m = -m;if( cntx >= n && cnty >= m ) printf( "YES\n" );else printf( "NO\n" );}return 0; }

B. New Colony

發現數據非常小,最暴力也只用滾1e51e51e5次就一定是?1-1?1,所以kkk那么大純粹蝦銀

#include <cstdio> #define maxn 105 int T, n, k; int h[maxn];int main() {scanf( "%d", &T );while( T -- ) {scanf( "%d %d", &n, &k );for( int i = 1;i <= n;i ++ )scanf( "%d", &h[i] );int ans;for( int i = 1;i <= k;i ++ ) {int pos = 1;for( int j = 2;j <= n;j ++ )if( h[pos] >= h[j] ) pos ++;else {h[pos] ++;break;}ans = pos;if( ans == n ) break;}if( ans == n ) printf( "-1\n" );else printf( "%d\n", ans );} return 0; }

C. Fence Painting

統計需要染色的顏色和個數,判斷是否足夠

對于無效的筆又必須使用,顯然將之用到最后一次有效操作的木板上

這樣之前的所有染色都會被覆蓋掉

注意最后一次有效操作的模板查找

#include <cstdio> #include <queue> using namespace std; #define maxn 100005 queue < int > q[maxn]; int T, n, m; int a[maxn], b[maxn], c[maxn], cnt[maxn]; bool vis[maxn];int main() {scanf( "%d", &T );again :while( T -- ) {scanf( "%d %d", &n, &m );for( int i = 1;i <= n;i ++ ) {while( ! q[i].empty() ) q[i].pop();vis[i] = cnt[i] = 0;}for( int i = 1;i <= n;i ++ )scanf( "%d", &a[i] );for( int i = 1;i <= n;i ++ )scanf( "%d", &b[i] ), vis[b[i]] = 1;for( int i = 1;i <= m;i ++ )scanf( "%d", &c[i] ), cnt[c[i]] ++;if( ! vis[c[m]] ) {printf( "NO\n" );goto again;}int pos;for( int i = 1;i <= n;i ++ ) {if( a[i] != b[i] ) q[b[i]].push( i );if( b[i] == c[m] && ( a[i] != b[i] || ( a[i] == b[i] && ! q[b[i]].size() ) ) ) pos = i;}for( int i = 1;i <= n;i ++ )if( q[b[i]].size() > cnt[b[i]] ) {printf( "NO\n" );goto again;}printf( "YES\n" );for( int i = 1;i <= m;i ++ )if( ! q[c[i]].empty() ) {printf( "%d ", q[c[i]].front() );q[c[i]].pop();}else printf( "%d ", pos );printf( "\n" );}return 0; }

D. AB Graph

大討論就是猴賽雷!!!

  • m=2k+1m=2k+1m=2k+1

    aba aaa都是回文串,由此可知不管邊長什么樣隨便選兩個點都是正確的

    在這里我們采取在(1,2)之間反復橫跳

  • m=2km=2km=2k

    • 先特判一下n=2n=2n=2的情況

    • 存在Ea→b=Eb→aE_{a\rightarrow b}=E_{b\rightarrow a}Eab?=Eba?,那么只需要在這樣一對邊橫跳即可,回文串只包含了一個字符

    • 一個簡單的三元環所經過的路徑字符一樣,直接繞環走

    • 不存在那么完美的兩種情況,這意味著一對邊一定是ab類型的

      顯然,任意三個點中一定會有至少一個點連出的兩條邊為ab

      (當控制另外兩個點連出邊一樣時,第三個點的邊就已確定)

      • m2=3t\frac{m}{2}=3t2m?=3t,走法bab
      • m2=3t+1\frac{m}{2}=3t+12m?=3t+1,走法abb
      • m2=3t+2\frac{m}{2}=3t+22m?=3t+2,走法bba

PS:代碼雖然看著冗長,但本質是ctrl+c ctrl+v (#.#)

#include <cstdio> #include <iostream> using namespace std; #define maxn 1005 int T, n, m; bool flag; char s[maxn][maxn];bool check0( int i, int j, int k ) {if( s[i][j] == 'b' && s[j][k] == 'a' && s[k][i] == 'b' ) return 1;else return 0; }bool check1( int i, int j, int k ) {if( s[i][j] == 'b' && s[j][k] == 'b' && s[k][i] == 'a' ) return 1;else return 0; }bool check2( int i, int j, int k ) {if( s[i][j] == 'a' && s[j][k] == 'b' && s[k][i] == 'b' ) return 1;else return 0; }void print( int i, int j, int k ) {printf( "YES\n" );for( int p = 0;p <= ( m << 1 );p ++ ) {printf( "%d ", i );int t = i;i = j;j = k;k = t;}printf( "\n" );flag = 1; }bool Check( int i, int j, int k ) {if( s[i][j] == s[j][k] && s[j][k] == s[k][i] ) return 1;else return 0; }int check( int i, int j ) {for( int k = 1;k <= n;k ++ )if( s[i][j] == s[j][k] ) return k;return 0; }void Print( int i, int j, int k ) {flag = 1;printf( "YES\n%d %d %d\n", i, j, k ); }int main() {scanf( "%d", &T );again :while( T -- ) {scanf( "%d %d", &n, &m );for( int i = 1;i <= n;i ++ )scanf( "%s", s[i] + 1 );if( m & 1 ) {int now = 1;printf( "YES\n" );for( int i = 0;i <= m;i ++ ) {printf( "%d ", now );now = 3 - now;}printf( "\n" );goto again;}else {for( int i = 1;i < n;i ++ )for( int j = i + 1;j <= n;j ++ )if( s[i][j] == s[j][i] ) {printf( "YES\n" );for( int k = 0;k <= m;k ++ ) {printf( "%d ", i );swap( i, j );}printf( "\n" );goto again;}if( n == 2 ) {printf( "NO\n" );goto again;}m >>= 1;flag = 0;if( m == 1 ) {int pos;if( pos = check( 1, 2 ) ) Print( 1, 2, pos );else if( pos = check( 1, 3 ) ) Print( 1, 3, pos );else if( pos = check( 2, 1 ) ) Print( 2, 1, pos );else if( pos = check( 2, 3 ) ) Print( 2, 3, pos );else if( pos = check( 3, 1 ) ) Print( 3, 1, pos );else if( pos = check( 3, 2 ) ) Print( 3, 2, pos );}else {flag = 0;int k = m % 3;switch( k ) {case 0 : {if( Check( 1, 2, 3 ) ) print( 1, 2, 3 );else if( check0( 1, 2, 3 ) ) print( 1, 2, 3 );else if( check0( 1, 3, 2 ) ) print( 1, 3, 2 );else if( check0( 2, 1, 3 ) ) print( 2, 1, 3 );else if( check0( 2, 3, 1 ) ) print( 2, 3, 1 );else if( check0( 3, 1, 2 ) ) print( 3, 1, 2 );else if( check0( 3, 2, 1 ) ) print( 3, 2, 1 );break;}case 1 : {if( Check( 1, 2, 3 ) ) print( 1, 2, 3 );else if( check1( 1, 2, 3 ) ) print( 1, 2, 3 );else if( check1( 1, 3, 2 ) ) print( 1, 3, 2 );else if( check1( 2, 1, 3 ) ) print( 2, 1, 3 );else if( check1( 2, 3, 1 ) ) print( 2, 3, 1 );else if( check1( 3, 1, 2 ) ) print( 3, 1, 2 );else if( check1( 3, 2, 1 ) ) print( 3, 2, 1 );break;}case 2 : {if( Check( 1, 2, 3 ) ) print( 1, 2, 3 );else if( check2( 1, 2, 3 ) ) print( 1, 2, 3 );else if( check2( 1, 3, 2 ) ) print( 1, 3, 2 );else if( check2( 2, 1, 3 ) ) print( 2, 1, 3 );else if( check2( 2, 3, 1 ) ) print( 2, 3, 1 );else if( check2( 3, 1, 2 ) ) print( 3, 1, 2 );else if( check2( 3, 2, 1 ) ) print( 3, 2, 1 );break;}}}if( ! flag ) printf( "NO\n" );}}return 0; }

E. Sorting Books

如果直接去求操作誰,顯然要考慮操作數量以及順序問題,順序問題一般都非常吃力不討好

反過來從后往前考慮,去求不操的數量的最大值即可,這時候就不需要管順序了

dpi:[i,n]dp_i:[i,n]dpi?:[i,n] 最大不操次數,li,ri:il_i,r_i:ili?,ri?:i 值出現的最左點和最右點,cntc:cnt_c:cntc?:iii位置為止ccc值出現的個數

  • 現在位置iii上的值的最左點就在iii處,那么貪心的可以選擇[i,n][i,n][i,n]所有與aia_iai?相同點不操作

    dprai+1+cntaidp_{r_{a_i}+1}+cnt_{a_i}dprai??+1?+cntai??

  • 最左點不在iii處,貪心的也可以選擇[i,n][i,n][i,n]所有出現的與aia_iai?相同點不操作

    cntaicnt_{a_i}cntai??

  • 位置iii操作

    dpi+1dp_{i+1}dpi+1?

#include <cstdio> #include <iostream> using namespace std; #define maxn 500005 int n; int a[maxn], l[maxn], r[maxn], cnt[maxn], dp[maxn];int main() {scanf( "%d", &n );for( int i = 1;i <= n;i ++ ) {scanf( "%d", &a[i] );if( ! l[a[i]] ) l[a[i]] = i;r[a[i]] = i;}for( int i = n;i;i -- ) {++ cnt[a[i]];dp[i] = dp[i + 1];if( i == l[a[i]] )dp[i] = max( dp[i], dp[r[a[i]] + 1] + cnt[a[i]] );elsedp[i] = max( dp[i], cnt[a[i]] );}printf( "%d\n", n - dp[1] );return 0; }

F. AB Tree

  • 每層點賦一樣的,可以使答案最優

    可以把每一層看成物品,物品的價值就是這一層的點數,跑一個01背包

    如果存在一組物品使得它們的和恰好為xxx,那么就直接輸出層數即可

  • 非要修改的話,修改單層的葉子結點,可以使答案最優

    先找到葉子節點最多的一層,試圖通過改當前層的葉子節點的狀態來彌補DPDPDP狀態

在此基礎上,需要套用bitset優化即可卡過去

#include <cstdio> #include <vector> #include <bitset> #include <iostream> using namespace std; #define maxn 100005 #define maxk 3000 vector < int > G[maxn], D[maxn]; int n, x, m; int dep[maxn], num[maxn], id[maxn], w[maxn], leaf_cnt[maxn]; bool vis[maxn]; bitset < maxn > f[maxk];void dfs1( int u, int fa ) {dep[u] = dep[fa] + 1;m = max( m, dep[u] );num[dep[u]] ++;if( G[u].size() == 1 ) leaf_cnt[dep[u]] ++;for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if( v == fa ) continue;else dfs1( v, u );} }void dfs2( int x, int y ) {if( ! x ) return;for( int i = 0;i < D[x].size();i ++ ) {if( w[x] > y || f[x - 1][y] ) break;y -= w[x];vis[D[x][i]] = 1;}dfs2( x - 1, y ); }int main() {scanf( "%d %d", &n, &x );for( int i = 2, fa;i <= n;i ++ ) {scanf( "%d", &fa );G[fa].push_back( i );G[i].push_back( fa );}dfs1( 1, 0 );int tot = 0;for( int i = 1;i <= n;i ++ ) {//merge depth i who has the same nodes in numbersif( ! id[num[i]] ) {id[num[i]] = ++ tot;w[tot] = num[i];D[tot].push_back( i );}else D[id[num[i]]].push_back( i );}f[0][0] = 1;for( int i = 1;i <= tot;i ++ ) {f[i] = f[i - 1];int siz = D[i].size();for( int j = 1;j <= siz;j <<= 1 ) {siz -= j;f[i] |= f[i] << j * w[i];}if( siz ) f[i] |= f[i] << siz * w[i];}if( f[tot][x] ) {printf( "%d\n", m );dfs2( tot, x );for( int i = 1;i <= n;i ++ )if( vis[dep[i]] ) printf( "a" );else printf( "b" );}else {printf( "%d\n", m + 1 );int ans;for( int i = x;~ i;i -- )if( f[tot][i] ) {ans = i;break;}dfs2( tot, ans );int pos = -1;for( int i = 1;i <= m;i ++ )if( ! vis[i] && leaf_cnt[i] >= x - ans ) {pos = i;break;}for( int i = 1;i <= n;i ++ )if( dep[i] == pos && G[i].size() == 1 ) {if( ans == x ) printf( "b" );else printf( "a" ), ans ++;}else {if( vis[dep[i]] ) printf( "a" );else printf( "b" );}}return 0; }

總結

以上是生活随笔為你收集整理的Codeforces Round #699 (Div. 2) 题解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。