首先先声明,这是作者的想法,严格证明都是比赛后证明的,如果有地方不妥,希望大家踊跃提出,作者会立刻改正虚心接受。
如果喜欢作者记得点赞关注哦~~~
A. Distinct Buttons
题意:一个遥控器一共四个方向,最多使用三个,使用四个会使遥控器坏掉,问从(0 , 0)出发,是否可以到达这n个点。
题解:统计方向即可。
代码:
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 2e5 + 7 ;
inline ll read(){
ll x = 0 , f = 1 ;
char c = getchar() ;
while(c > '9' || c < '0'){
if(c == '-')
f = -1 ;
c = getchar() ;
}
while(c >= '0' && c <= '9'){
x = x * 10 + c - '0' ;
c = getchar() ;
}
return x * f ;
}
char s[maxn] , S[maxn] ;
ll t , n , k , q , a[maxn] ;
bool vis[maxn] ;
ll b[maxn] ;
void solve(){
n = read() ;
for(int i = 1 ; i <= 4 ; i ++){
vis[i] = 0 ;
}
for(int i = 1 ; i <= n ; i ++){
a[i] = read() ;
b[i] = read() ;
}
for(int i = 1 ; i <= n ; i ++){
if(a[i] < 0){
vis[1] = 1 ;
}
if(a[i] > 0){
vis[2] = 1 ;
}
if(b[i] < 0){
vis[3] = 1 ;
}
if(b[i] > 0){
vis[4] = 1;
}
}
int Cnt = 0 ;
for(int k = 1 ; k <= 4 ; k ++){
if(vis[k] == 1){
Cnt ++ ;
}
}
if(Cnt <= 3){
cout << "YES\n" ;
return ;
}
cout << "NO\n" ;
}
int main(){
t = read() ;
while(t --){
solve() ;
}
return 0 ;
}
B. Make Almost Equal With Mod
题意:一共有n个数,要选出一个x作为模数,让所有的数字(mod)X后只有两个数字。
题解:首先如果有奇数有偶数,可以直接mod 2 , 这很显然。再看数据很大,10的18次方,可以想到二进制枚举。
代码:
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 1e6 + 7 ;
inline ll read(){
ll x = 0 , f = 1 ;
char c = getchar() ;
while(c > '9' || c < '0'){
if(c == '-')
f = -1 ;
c = getchar() ;
}
while(c >= '0' && c <= '9'){
x = x * 10 + c - '0' ;
c = getchar() ;
}
return x * f ;
}
char s[maxn] , S[maxn] ;
ll t , n , k , q ;
bool vis[maxn] ;
ll b[maxn] ;
void solve(){
n = read() ;
vector < ll > a(n) ;
for(int i = 0 ; i < n ; i ++){
a[i] = read() ;
}
ll ji = 0 , ou = 0 ;
for(int i = 0 ; i < n ; i ++){
if(a[i] % 2ll == 0){
ou ++ ;
}
else{
ji ++ ;
}
}
if(ou > 0 && ji > 0 ){
cout << 2 << endl ;
return ;
}
for(int i = 1 ; ; i ++){
ll res = (1ll << i) ;
set < ll > q ;
for(auto it : a){
q.insert(it % res) ;
}
if(q.size() == 2){
cout << res << endl ;
return ;
}
}
}
int main(){
t = read() ;
while(t --){
solve() ;
}
return 0 ;
}
C. Heavy Intervals
题意:一共给你三个数组a , b , c ,你可以任意将这三组数据排序,求出可以将(b[i] - a[i]) * c[i] (i = 1 - n)求和的最大值。
题解:首先只要没有两条相交的线段(不是包含,而是相交) ,可以看到(b[i] - a[i])全部的和是一定的,那必然要将小的值给大的区间。因为我们想让每个区间长度最大,所以如果L确定,有R1 > L , R2 > L , R2 > R1 ,我们应该优先选择R1 , 这样可以使每个区间的长度最大。所以从大数开始枚举,二分求出第一个比他大的数字,依次进行,可以想到用set维护,好处理一点。
备注:没有看到resubmission会扣分,手欠又交了一发,导致掉了打分!
代码:
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 4e5 + 7 ;
inline ll read(){
ll x = 0 , f = 1 ;
char c = getchar() ;
while(c > '9' || c < '0'){
if(c == '-')
f = -1 ;
c = getchar() ;
}
while(c >= '0' && c <= '9'){
x = x * 10 + c - '0' ;
c = getchar() ;
}
return x * f ;
}
char s[maxn] , S[maxn] ;
ll t , n , k , q , a[maxn] , c[maxn] ;
bool vis[maxn] ;
ll b[maxn] , d[maxn] ;
void solve(){
n = read() ;
for(int i = 1 ; i <= n ; i ++){
a[i] = read() ;
}
for(int i = 1 ; i <= n ; i ++){
b[i] = read() ;
}
for(int i = 1 ; i <= n ; i ++){
c[i] = read() ;
}
ll ans = 0 ;
sort(a + 1 , a + n + 1 , greater<>()) ;
sort(b + 1 , b + n + 1 , greater<>()) ;
multiset < ll > q ;
for(int i = 1 ; i <= n ; i ++){
q.insert(b[i]) ;
}
for(int i = 1 ; i <= n ; i ++){
auto it = q.lower_bound(a[i]) ;
// cout << *it << endl ;
d[i] = *it - a[i] ;
q.erase(*it) ;
}
sort(c + 1 , c + n + 1) ;
sort(d + 1 , d + n + 1 , greater<>()) ;
for(int i = 1 ; i <= n ; i ++){
ans += d[i] * c[i] ;
}
cout << ans << endl ;
}
int main(){
t = read() ;
while(t --){
solve() ;
}
return 0 ;
}