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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[AtCoder Beginner Contest 216] 题解

發布時間:2023/12/3 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [AtCoder Beginner Contest 216] 题解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • A - Signed Difficulty
  • B - Same Name
  • C - Many Balls
  • D - Pair of Balls
  • E - Amusement Park
  • F - Max Sum Counting
  • G - 01Sequence

比賽鏈接

A - Signed Difficulty

簽到題

#include <cstdio> int x, y; char c; int main() {scanf( "%d%c%d", &x, &c, &y );if( y <= 2 ) printf( "%d-", x );else if( y >= 7 ) printf( "%d+", x );else printf("%d", x );return 0; }

B - Same Name

簽到題

#include <cstdio> #include <iostream> #include <map> using namespace std; map < pair < string, string >, int > mp; int n;int main() {scanf( "%d", &n );for( int i = 1;i <= n;i ++ ) {string a, b;cin >> a >> b;if( mp[make_pair( a, b )] ) return ! printf( "Yes\n" );mp[make_pair( a, b )] = 1;}printf( "No\n" );return 0; }

C - Many Balls

簡單題

發現是快速冪的逆過程

#include <cstdio> #include <vector> using namespace std; #define int long long vector < int > ans; int n;signed main() {scanf( "%lld", &n );while( n ) {if( n & 1 ) ans.push_back( 0 );ans.push_back( 1 );n >>= 1;}for( int i = ans.size() - 1;~ i;i -- )printf( "%c", ans[i] + 'A' );return 0; }

D - Pair of Balls

超難題!!!靠

不搞環,硬漢就搞大模擬

記錄顏色兩次出現位置,并帶上標記,成為堆頂為000,在下面為111

當顏色兩個位置都入隊(成為其所在堆的堆頂)

彈出,并把堆下面一個元素標記為新的堆頂

就這么模擬,凸(艸皿艸 )

之前打的什么鬼傻逼set/map半天模擬不動,又TLE又RE又WA

o(╥﹏╥)o _(|3」∠)_ ┏┛墓┗┓…(((m-__-)m

#include <cstdio> #include <vector> #include <queue> #include <iostream> using namespace std; #define maxn 200005 struct node {int color, i, rnk, pos;node(){}node( int C, int I, int R, int P ) {color = C, i = I, rnk = R, pos = P;} }c[maxn][2]; int n, m, cnt; queue < node > q; vector < int > g[maxn]; bool vis[maxn][2];int main() {scanf( "%d %d", &n, &m );for( int i = 1, k, x;i <= m;i ++ ) {scanf( "%d", &k );for( int j = 1;j <= k;j ++ ) {scanf( "%d", &x );g[i].push_back( x );if( ! vis[x][0] ) c[x][0] = node( x, i, j, 1 ), vis[x][0] = 1;else c[x][1] = node( x, i, j, 1 ), vis[x][1] = 1;}}for( int i = 1;i <= n;i ++ ) {auto ls = c[i][0];auto rs = c[i][1];vis[i][0] = vis[i][1] = 0;if( ! ls.pos and ! rs.pos ) {q.push( c[i][0] );q.push( c[i][1] );}}while( ! q.empty() ) {auto ls = q.front(); q.pop();auto rs = q.front(); q.pop();cnt ++;int nxt;if( ls.rnk ^ g[ls.i].size() ) {nxt = g[ls.i][ls.rnk];if( c[nxt][0].i == ls.i ) c[nxt][0].pos = 0;else c[nxt][1].pos = 0;if( ! c[nxt][0].pos and ! c[nxt][1].pos ) {q.push( c[nxt][0] );q.push( c[nxt][1] );}}if( rs.rnk ^ g[rs.i].size() ) {nxt = g[rs.i][rs.rnk];if( c[nxt][0].i == rs.i ) c[nxt][0].pos = 0;else c[nxt][1].pos = 0;if( ! c[nxt][0].pos and ! c[nxt][1].pos ) {q.push( c[nxt][0] );q.push( c[nxt][1] );}}}if( cnt ^ n ) printf( "No\n" );else printf( "Yes\n" );return 0; }

E - Amusement Park

簡單題

數學直接算

從大到小取,每次a[i]a[i]a[i]取到a[i+1]a[i+1]a[i+1]相同值就停,等差數列算這中間的值和

隨著iii的枚舉,前面全是相同的a[i]a[i]a[i],所以這等差數列算了后還要乘以一個iii的系數

#include <cstdio> #include <algorithm> using namespace std; #define int long long #define maxn 100005 int n, k; int a[maxn];signed main() {scanf( "%lld %lld", &n, &k );for( int i = 1;i <= n;i ++ )scanf( "%lld", &a[i] );sort( a + 1, a + n + 1, []( int x, int y ) { return x > y; } );int ans = 0;for( int i = 1;i <= n;i ++ ) {int x = a[i] - a[i + 1];int sum = ( a[i] + a[i + 1] + 1 ) * x / 2;if( k <= x * i ) {x = k / i;sum = ( a[i] + a[i] - x + 1 ) * x / 2;ans += sum * i;a[i] -= k / i;k %= i;ans += a[i] * k;break;}else {ans += sum * i;k -= x * i;}}printf( "%lld\n", ans );return 0; }

F - Max Sum Counting

簡單題

凸(艸皿艸 ),傻逼背包倒DP調nm半個小時

AAA排序,枚舉AiA_iAi?作為最大值

接下來就是選一些數滿足BjB_jBj?的和不超過AiA_iAi?

dpj:dp_j:dpj?: 和為jjj的方案數

每次統計答案后,再轉移iiiBiB_iBi?的貢獻

發現其實就是個簡單背包

#include <cstdio> #include <algorithm> using namespace std; #define int long long #define mod 998244353 #define maxn 5005 struct node { int a, b; }g[maxn]; int n; int t[maxn], dp[maxn];bool cmp( node x, node y ) {return x.a < y.a; }signed main() {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &g[i].a );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &g[i].b );sort( g + 1, g + n + 1, cmp );int ans = 0;dp[0] = 1;for( int i = 1;i <= n;i ++ ) {for( int j = 0;j <= g[i].a - g[i].b;j ++ )ans = ( ans + dp[j] ) % mod;for( int j = maxn - 1;j >= g[i].b;j -- )dp[j] = ( dp[j] + dp[j - g[i].b] ) % mod;}printf( "%lld\n", ans );return 0; }

G - 01Sequence

看完題目是非常板的差分約束題面感

sis_isi?表示1?i1-i1?i中1的個數

[l,r][l,r][l,r]區間內1個數不少于xxx個,翻譯約束為sr?sl?1≥xs_r-s_{l-1}\ge xsr??sl?1?x

為了契合差分約束的≤\le

重新定義sis_isi?表示1?i1-i1?i中0的個數

翻譯約束為sr?sl?1≤r?l+1?xs_r-s_{l-1}\le r-l+1-xsr??sl?1?r?l+1?x

轉化到圖論上,連邊l?1→rl-1\rightarrow rl?1r有向邊的邊權r?l+1?xr-l+1-xr?l+1?x

跑最短路即可

本題卡SPFA

差分約束

  • 為什么是≤\le約束(不等式左邊為“點”,不等式右邊為固定限制)

    • 首先最長路目前沒有快速地算法
    • 其次符合最短路disv≤disu+wu,vdis_v\le dis_u+w_{u,v}disv?disu?+wu,v?的形式
  • 感覺最后求sns_nsn?的最大值,應該是最長路,為什么圖論上是跑最短路

    • 首先約束和sns_nsn?之間是逆向關系,并不是正比于

    • 可以理解為最短路就是求出最嚴格的約束

    • sns_nsn?的所有值都保證要滿足所有的約束,自然要滿足最嚴格的約束

    • e.g. (i,j)=x1,(j,k)=x2,(i,k)=x3,x1+x2<x3(i,j)=x_1,(j,k)=x_2,(i,k)=x_3,x_1+x_2<x_3(i,j)=x1?,(j,k)=x2?,(i,k)=x3?,x1?+x2?<x3?

      既要滿足disj≤disi+x1;disk≤disj+x2dis_j\le dis_i+x_1;dis_k\le dis_j+x_2disj?disi?+x1?;disk?disj?+x2?

      又要滿足disk≤disi+x3dis_k\le dis_i+x_3disk?disi?+x3?

      并且disk≤disj+x2≤disi+x1+x2≤disi+x3dis_k\le dis_j+x_2\le dis_i+x_1+x_2\le dis_i+x_3disk?disj?+x2?disi?+x1?+x2?disi?+x3?

      根據不等式的原則,同小取小的最嚴格約束

      這恰好匹配最短路的過程

所以差分約束的本質是轉化為最短路問題

#include <queue> #include <cstdio> #include <vector> #include <cstring> #include <iostream> using namespace std; #define maxn 200005 #define Pair pair < int, int > priority_queue < Pair, vector < Pair >, greater < Pair > > q; int n, m; int dis[maxn]; bool vis[maxn]; vector < Pair > G[maxn];void addedge( int u, int v, int w ) {G[u].push_back( make_pair( v, w ) ); }int main() {scanf( "%d %d", &n, &m );for( int i = 1, l, r, x;i <= m;i ++ ) {scanf( "%d %d %d", &l, &r, &x );addedge( l - 1, r, r - l + 1 - x );}for( int i = 0;i < n;i ++ ) {addedge( i, i + 1, 1 );addedge( i + 1, i, 0 );}memset( dis, 0x3f, sizeof( dis ) );dis[0] = 0; q.push( make_pair( 0, 0 ) );while( ! q.empty() ) {Pair now = q.top(); q.pop();int u = now.second;if( vis[u] or dis[u] ^ now.first ) continue;vis[u] = 1;for( auto nxt : G[u] ) {int v = nxt.first, w = nxt.second;if( dis[v] > dis[u] + w ) {dis[v] = dis[u] + w;q.push( make_pair( dis[v], v ) );}}}for( int i = 1;i <= n;i ++ )printf( "%d ", ( dis[i] - dis[i - 1] ) ^ 1 );return 0; }

總結

以上是生活随笔為你收集整理的[AtCoder Beginner Contest 216] 题解的全部內容,希望文章能夠幫你解決所遇到的問題。

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