Educational Codeforces Round 55 (Rated for Div. 2) A模拟 B前缀和 C前缀和,排序 D构造 E dp

A

Code:

#include 
#define INF 0x3f3f3f3f
using namespace std;
int main(){
	int T;
	cin >> T;
	while( T-- ){
		int n , x , y , d; 
		cin >> n >> x >> y >> d ; 
		if( y == x ) printf("0\n");
		else{
			if( abs( y - x ) % d == 0 ){
				printf("%d\n",abs( y - x ) / d ) ;
			}else{
				int res = INF ;
				if( ( n - y ) % d == 0 ){
					res = ( n - x ) / d + ( ( n - x ) % d != 0 ) ;
					res += ( n - y ) / d ; 
				}

				if( ( y - 1 ) % d == 0 ){
					x -- ; 
					int num = x / d + ( x % d != 0 ) ;
					num += ( y - 1 ) / d ; 
					res = min( res , num ) ;
				}
				if( res < INF ) printf("%d\n",res);
				else printf("-1\n");
			}
		}
	}
	return 0 ; 
}

B
Code:

#include 
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 2e5 + 66 ;
int rear[AX] ; 
int pre[AX] ;
char s[AX] ; 
int main(){
	int n ;
	scanf("%d%s",&n,s+1);
	int tot = 0 ; 
	pre[0] = 0 ;  
	rear[n+1] = 0 ; 
	int res = 0 ;
	for( int i = 1 ; i <= n ; i ++ ){  //wei 
		if( s[i] == 'G' ){
			tot ++ ; 
			pre[i] = pre[i-1] + 1 ;
		}else pre[i] = 0 ; 
		res = max( res , pre[i] ) ; 
	}
	for( int i = n ; i >= 1 ; i -- ){ //tou
		if( s[i] == 'G' ){
			rear[i] = rear[i+1] + 1 ;
		}else rear[i] = 0 ; 
	}
	s[0] = 'S';
	s[n+1] = 'S' ; 
	for( int i = 1 ; i <= n ; i++ ){
		if( s[i] == 'S' ){
			if( s[i-1] == 'G' && tot > pre[i-1] ){
				res = max( res , pre[i-1] + 1 ) ; 
			}
			if( s[i+1] == 'G' && tot > rear[i+1] ){
				res = max( res , rear[i+1] + 1 ) ; 
			}
			if( s[i-1] == 'G' && s[i+1] == 'G' ){
				if( tot > pre[i-1] + rear[i+1] ){
					res = max( res , pre[i-1] + rear[i+1] + 1 ) ; 
				}else{
					res = max( res , pre[i-1] + rear[i+1] ) ; 
				}
			}
		}
	}
	printf("%d\n",res);
	return 0 ; 
}

C
思路:每门科目所拥有的按从大到小排序,记录前缀和,然后在计算不同长度的总共的最大值,
Code:

#include 
#define LL long long 
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 2e5 + 666 ;
std::vector<int> v[AX];
LL sum[AX] ; 
bool cmp( int a , int b ){
	return a > b ; 
}
int main(){
	int n , m ;
	scanf("%d%d",&n,&m) ; 
	int x ;
	LL y ; 
	for( int i = 0 ; i < n ; i++ ){
		scanf("%d%I64d",&x,&y);
		v[x].push_back(y) ; 
	}
	int len = 0 ;
	for( int i = 1 ; i <= m ; i++ ){
		sort( v[i].begin() , v[i].end() , cmp ) ; 
		len = max( len , (int)v[i].size() ) ; 
	}
	for( int i = 1 ; i <= m ; i++ ){
		int k = v[i].size() ; 
		for( int j = 1 ; j < k ; j++ ){
			v[i][j] += v[i][j-1] ;
		}
	}
	LL res = 0LL ; 
	for( int i = 1 ; i <= m ; i ++ ){
		for( int j = 0 ; j < v[i].size() ; j++ ){
			if( v[i][j] > 0 ){
				sum[j+1] += v[i][j] ;
			}
		}
	}
	for(int i=1;i<=len;i++){
		res=max(sum[i],res);
	}
	printf("%I64d\n",res);
	return 0 ; 
}

D
思路:两个度以上的连起来,两头连接一个度的,剩下一度的在分支。
Code:

#include 
using namespace std;
const int AX = 5e2 + 6 ;
struct Node{
	int id ; 
	int d ; 
	bool operator < ( const Node &ch )const{
		return d > ch.d ; 
	}
}a[AX];
std::vector<int> G[AX];
int cnt[AX] ; 
int main(){
	int n ;
	scanf("%d",&n) ; 
	int tot = 0 ; 
	for( int i = 1 ; i <= n ; i++ ){
		scanf("%d",&a[i].d) ;
		cnt[i] = a[i].d ; 
		if( a[i].d > 1 ) tot ++ ; 
		a[i].id = i ; 
	}
	sort( a + 1 , a + n + 1 ) ; 
	stack<int>s;
	G[a[1].id].push_back(a[n].id) ; 
	cnt[a[1].id] -- ; 
	cnt[a[n].id] -- ; 
	if( cnt[a[1].id] ) s.push( a[1].id ) ;
	int m = 1 ; 
	for( int i = 2 ; i <= n - 1 ; i++ ){
		if( s.size() ){
			int x = s.top() ; 
			G[x].push_back(a[i].id); 
			m ++ ; 
			if( --cnt[x] == 0 ){
				s.pop() ; 
			}
			if( --cnt[a[i].id] > 0 ){
				s.push(a[i].id) ; 
			}
		}else{
			return 0*printf("NO\n");
		}
	}
	printf("YES %d\n",min(n-1,tot+1));
	printf("%d\n",m);
	for( int i = 1 ; i <= n ; i++ ){
		for( int j = 0 ; j < G[i].size() ; j++ ){
			printf("%d %d\n",i,G[i][j]);
		}
	}
	return 0 ; 
}

E

思路:这题思路倒是不难想,看了一个很简单的实现,以后要多用c11特性。
sum[i] 为1-i中c的个数
cnt[i]为 1 - i中x的个数
要求最后最大的c个数,就是找一个区间[l,r]让其中的x都加上c-x,这样,原先该区间的x变为c,原先该区间的c就不是c了。
所以res = max( sum[n] - sum[r] + sum[l-1] + cnt[r] - cnt[l-1] )
上面删除线部分在r一定时都是固定的,
所以我们求max( sum[l-1] - cnt[l-1] )
一路维护这个值就行了。

Code:

#include 
using namespace std;
const int AX = 5e5 + 6 ;  
int a[AX] ; 
int sum[AX] ; 
map<int,std::vector<int> >mp;
int cnt[AX] ; 
int main(){
	int n , c ;
	scanf("%d%d",&n,&c) ;
	int res = 0 ; 
	for( int i = 1 ; i <= n ; i++ ){
		scanf("%d",&a[i]) ; 
		if( a[i] == c ) res ++ ; 
		sum[i] = sum[i-1] + ( a[i] == c ) ;
		mp[a[i]].push_back(i) ; 
	}
	for( auto i : mp ){
		std::vector<int> tmp = i.second ;
		int val = i.first , t = 0 ; 
		for( const auto &pos : tmp ){
			t = max( sum[pos-1] - cnt[val] , t ) ; 
			cnt[val] ++ ;
			res = max( res , sum[n] - sum[pos] + cnt[val] + t ) ; 
		}
	}
	printf("%d\n",res);
	return 0 ; 
}

你可能感兴趣的:(贪心)