Codeforces Round #510 (Div. 2) A 模拟 B枚举 C D离散化+树状数组(逆序对)

版权声明:本文为博主原创文章,未经博主允许也可以转载。 https://blog.csdn.net/FrankAx/article/details/82818301

A

Code:

#include <bits/stdc++.h>
#define LL long long 
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 1e5+66;
int a[AX];
int main(){
   	int n , m ; 
   	scanf("%d%d",&n,&m);
   	int x ;
   	int mm = m ;
   	int maxn = 0 ; 
   	for( int i = 0 ; i < n ; i++ ){
   		scanf("%d",&a[i]);
   		maxn = max( maxn , a[i] ) ;
   	}
   	int minus = maxn ; 
   	for( int i = 0 ; i < n ; i++ ){
   		if( maxn > a[i] ){
   			m -= ( maxn - a[i] ) ;
   		}
   	}
   	if( m > 0 ){
   		minus += ( m / n );
   		m %= n ; 
   		if( m ) minus ++ ;
   	}
   	printf("%d %d\n", minus , maxn + mm );
    return 0 ; 
}

B

Code:

#include <bits/stdc++.h>
#define LL long long 
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 1e5+66;
map<char,int>mp;
int a[AX];
int main(){
	int n ;
	char s[10];
	mp['A'] = 10 ;
	mp['B'] = 11 ;
	mp['C'] = 12 ;
	int x ;
	scanf("%d",&n);
	memset( a, INF , sizeof(a));
	for( int i = 0 ; i < n ; i++ ){
		scanf("%d%s",&x,s);
		int len = strlen(s) ;
		int val = 0 ; 
		for( int i = 0 ; i < len ; i++ ){
			val += mp[s[i]] ;
		}
		a[val] = min( a[val] , x ) ;
	}
	int res = INF ;
	if( a[33] < INF ){
		res = min( res , a[33] ) ;
	}
	if( a[21] < INF && a[12] < INF ){
		res = min( a[21] + a[12] , res ) ;
	}
	if( a[22] < INF && a[11] < INF ){
		res = min( a[22] + a[11] , res ) ;
	}
	if( a[23] < INF && a[10] < INF ){
		res = min( a[23] + a[10] , res ) ;
	}
	if( a[10] < INF && a[11] < INF && a[12] < INF ){
		res = min( res , a[10] + a[11] + a[12] ) ;
	}
	if( a[21] < INF && a[22] < INF ){
		res = min( res , a[21] + a[22] ) ;
	}
	if( a[21] < INF && a[23] < INF ){
		res = min( res , a[21] + a[23] ) ;
	}
	if( a[22] < INF && a[23] < INF ){
		res = min( res , a[22] + a[23] ) ;
	}
	if( res == INF ) printf("-1\n");
	else printf("%d\n",res);
	return 0 ; 
}


D
题意:求有多少个区间[L,R]满足 a[L] +…+ a[R] < t .
思路:求出前缀和L[i] ,
那么结果就是 L[j] - L[i-1] < t (相当于a[i] +…+a[j] < t )
转化下就是 L[i-1] > L[j] - t ;
然后离散化,逐个枚举L[j] ,就成了找小于j的前缀和中,有几个大于R[j] - t,这就成了求逆序对的题目。

#include <bits/stdc++.h>
#define LL long long 
#define INF 0x3f3f3f3f
#define ios ios_base::sync_with_stdio(false); cin.tie(0) ; cout.tie(0); 
using namespace std;
const int AX = 2e5+1;
int n ;
LL L[AX];
std::vector<LL> v;
LL c[AX*2];
int get_id( LL x ){
	int idx = lower_bound( v.begin() , v.end() , x ) - v.begin() ; 
	return ( v[idx] == x ? idx + 1 : idx ) ; 
}	

int lowbit( int x ){
	return x & (-x) ;
}

void update( int site , int val ){
	while( site <= n ){
		c[site] += val ; 
		site += lowbit( site ) ;
	}
}

LL query( int x ){
	LL ans = 0 ;
	while( x >= 1 ){
		ans += c[x];
		x -= lowbit(x);
	}
	return ans ; 
}

int main(){
	LL t ; 
	LL res = 0LL ;
	ios ;
	cin >> n >> t ; 
	LL x ;
	cin >> x ; L[0] = x;
	if( x < t ) res ++ ;  
	v.push_back(L[0]);
	for( int i = 1 ; i < n ; i++ ){
		cin >> x ; 
		L[i] = L[i-1] + x ; 
		v.push_back(L[i]) ; 
	}
	sort( v.begin() , v.end() ) ;
	v.erase( unique( v.begin() , v.end() ) , v.end() );
	update( get_id(L[0]) , 1 );
	for( int i = 1 ; i < n ; i++ ){
		if( L[i] < t ) res ++ ; 
		res += ( i - query(get_id(L[i]-t)) ) ; 
		update( get_id(L[i]) , 1 ) ;
	}
	cout << res << endl;
	return 0 ; 
}


猜你喜欢

转载自blog.csdn.net/FrankAx/article/details/82818301
今日推荐