Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round) 题解
文章目錄
- A. Prison Break
- B. Restore Modulo
- C. Basic Diplomacy
- D. Playlist
- E. Skyline Photo
- F. Useful Edges
#709 (Div. 2)
A. Prison Break
就是每個監獄破一扇門,輸出a×ba\times ba×b即可
B. Restore Modulo
就是取模意義下的操作,分大小操作,隨便確定兩個差值,然后構造即可
#include <cstdio> #include <iostream> using namespace std; #define int long long #define maxn 100005 int T, n; int a[maxn];signed main() {scanf( "%lld", &T );while( T -- ) {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ )scanf( "%lld", &a[i] );if( n == 1 ) {printf( "0\n" );continue;}int d1 = -1, d2 = -1;bool flag = 0;for( int i = 1;i < n;i ++ )if( a[i + 1] > a[i] )if( ~ d1 )if( a[i + 1] - a[i] != d1 ) {flag = 1;break;} else;else d1 = a[i + 1] - a[i];elseif( ~ d2 )if( a[i] - a[i + 1] != d2 ) {flag = 1;break;} else;else d2 = a[i] - a[i + 1];if( flag ) printf( "-1\n" );else if( d1 == -1 || d2 == -1 ) printf( "0\n" );else {int maxx = 0;for( int i = 1;i <= n;i ++ ) maxx = max( maxx, a[i] );if( d1 + d2 <= maxx ) printf( "-1\n" );else printf( "%lld %lld\n", d1 + d2, ( a[2] + d1 + d2 - a[1] ) % ( d1 + d2 ) );}}return 0; }C. Basic Diplomacy
貪心,對于某天有多種選擇的肯定優先滿足限制比較死的,比如某天就必須和某人玩
發現,只要k=1k=1k=1的條件滿足,后面只要使用次數沒超過一半就可以跟那個人玩
#include <cstdio> #include <vector> #include <algorithm> using namespace std; #define maxn 100005 vector < int > G[maxn]; int T, n, m; int cnt[maxn], ans[maxn], used[maxn];int main() {scanf( "%d", &T );while( T -- ) {scanf( "%d %d", &n, &m );for( int i = 1;i <= n;i ++ ) cnt[i] = used[i] = 0;for( int i = 1;i <= m;i ++ ) G[i].clear();for( int i = 1, k;i <= m;i ++ ) {scanf( "%d", &k );for( int j = 1, x;j <= k;j ++ ) {scanf( "%d", &x );G[i].push_back( x );cnt[x] ++;}if( k == 1 ) ans[i] = G[i][0], used[G[i][0]] ++;}int lim = ( m + 1 ) >> 1;for( int i = 1;i <= m;i ++ )if( G[i].size() == 1 ) continue;else {for( int j = 0;j < G[i].size();j ++ )if( used[G[i][j]] >= lim ) continue;else {ans[i] = G[i][j];used[G[i][j]] ++;break;}}bool flag = 0;for( int i = 1;i <= n;i ++ )if( used[i] > lim ) {flag = 1;break;}if( flag ) printf( "NO\n" );else {printf( "YES\n" );for( int i = 1;i <= m;i ++ )printf( "%d ", ans[i] );printf( "\n" );}}return 0; }D. Playlist
想復雜了——就是分類大討論
可以找兩個質數,例如1e9+91e9+91e9+9,遇到不互質的時候就賦質數
#include <cstdio> #include <queue> using namespace std; #define maxn 100005 queue < int > q, ans; int T, n; int a[maxn], pos[maxn]; bool vis[maxn];int gcd( int x, int y ) {if( ! y ) return x;else return gcd( y, x % y ); }int main() {scanf( "%d", &T );while( T -- ) {scanf( "%d", &n );for( int i = 1;i <= n;i ++ ) vis[i] = pos[i] = 0;for( int i = 1;i <= n;i ++ ) scanf( "%d", &a[i] );for( int i = 1;i < n;i ++ )if( gcd( a[i], a[i + 1] ) == 1 )ans.push( i + 1 ), vis[i + 1] = 1, q.push( i ), pos[i] = i + 1, i ++;if( ! vis[n] && gcd( a[n], a[1] ) == 1 ) ans.push( 1 ), vis[1] = 1, q.push( n ), pos[n] = 2;while( ! q.empty() ) {int t = q.front(); q.pop();if( vis[t] ) continue;if( pos[t] == n + 1 ) pos[t] = 1;while( vis[pos[t]] )pos[t] = pos[t] == n ? 1 : pos[t] + 1;if( gcd( a[pos[t]], a[t] ) == 1 ) ans.push( pos[t] ), vis[pos[t]] = 1, q.push( t ), pos[t] ++;}printf( "%d ", ans.size() );while( ! ans.empty() ) printf( "%d ", ans.front() ), ans.pop();printf( "\n" );}return 0; }E. Skyline Photo
普通的DPDPDP式子:dpi=dpj+w(j+1,i)dp_i=dp_j+w(j+1,i)dpi?=dpj?+w(j+1,i)
w(j+1,i)w(j+1,i)w(j+1,i)事實上是單調棧更新到iii時,棧里面第一個下標大于jjj的房子的美麗度
對于棧里面的第iii個元素,管轄著區間(si?1,si](s_{i-1},s_i](si?1?,si?],維護的是遞增的單調棧
fi=maxk=1top(maxj=sk?1+1skfj+bsk)f_i=max_{k=1}^{top}(max_{j=s_{k-1}+1}^{s_k}f_j+b_{s_k})fi?=maxk=1top?(maxj=sk?1?+1sk??fj?+bsk??)
#include <cstdio> #include <iostream> using namespace std; #define int long long #define maxn 300005 int n, top; int h[maxn], b[maxn], s[maxn], g[maxn], f[maxn], dp[maxn];signed main() {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ )scanf( "%lld", &h[i] );for( int i = 1;i <= n;i ++ )scanf( "%lld", &b[i] );g[0] = -1e18;for( int i = 1;i <= n;i ++ ) {int t = dp[i - 1];while( top && h[s[top]] > h[i] ) {t = max( t, f[top] );top --;}s[++ top] = i, f[top] = t;dp[i] = g[top] = max( g[top - 1], t + b[i] );/*(s[top-1],i]這一段被彈出的元素高度都比i高g[top-1]:把(s[top-1],i]這一段跟[1,s[top-1]]合并 答案就在比i矮的s[top-1]身上t+b[i]: (s[top-1],i]單獨成段 最矮的就是i */}printf( "%lld\n", dp[n] );return 0; }F. Useful Edges
如果一條邊(x,y,c)(x,y,c)(x,y,c)和三元組(u,v,l)(u,v,l)(u,v,l),滿足disu,x+c+disv,y≤ldis_{u,x}+c+dis_{v,y}\le ldisu,x?+c+disv,y?≤l,則該邊合法
目前來看是非常樸素的O(n4)O(n^4)O(n4),數據范圍只能承受O(n3)O(n^3)O(n3),考慮降維(對角線想法)
disu,x+c+disv,y≤l?disv,y+c≤l?disu,xdis_{u,x}+c+dis_{v,y}\le l \Leftrightarrow dis_{v,y}+c\le l-dis_{u,x}disu,x?+c+disv,y?≤l?disv,y?+c≤l?disu,x?
只需要枚舉u,x,vu,x,vu,x,v便能求出l?disu,xl-dis_{u,x}l?disu,x?的最大值,再u,x,yu,x,yu,x,y找到左邊滿足條件的邊(v,yv,yv,y同地位循環)
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define int long long #define maxn 605 pair < int, int > edge[maxn * maxn / 2]; int dis[maxn][maxn], w[maxn][maxn], l[maxn][maxn]; bool flag[maxn][maxn]; int u[maxn], v[maxn]; int n, m, Q, ans;signed main() {memset( dis, 0x3f, sizeof( dis ) );scanf( "%lld %lld", &n, &m );for( int i = 1, u, v, c;i <= m;i ++ ) {scanf( "%lld %lld %lld", &u, &v, &c );edge[i] = make_pair( u, v );w[u][v] = w[v][u] = dis[u][v]= dis[v][u] = c;}for( int i = 1;i <= n;i ++ )dis[i][i] = 0;for( int k = 1;k <= n;k ++ )for( int i = 1;i <= n;i ++ )for( int j = 1;j <= n;j ++ )dis[i][j] = min( dis[i][j], dis[i][k] + dis[k][j] );scanf( "%lld", &Q );while( Q -- ) {int u, v, x;scanf( "%lld %lld %lld", &u, &v, &x );l[u][v] = l[v][u] = max( l[u][v], x );}for( int v = 1;v <= n;v ++ ) {for( int x = 1;x <= n;x ++ ) {int maxx = 0;for( int u = 1;u <= n;u ++ )maxx = max( maxx, l[u][v] - dis[u][x] );for( int y = 1;y <= n;y ++ ) {if( dis[y][v] + w[x][y] <= maxx ) flag[x][y] = flag[y][x] = 1;}}}int ans = 0;for( int i = 1;i <= m;i ++ )if( flag[edge[i].first][edge[i].second] ) ans ++;printf( "%lld\n", ans );return 0; }總結
以上是生活随笔為你收集整理的Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round) 题解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么样才能找到网站后台网址()
- 下一篇: 小米手机6种截屏方法,很多人只用过一两种