Pinely Round 3 (Div. 1 + Div. 2)

A. Distinct Buttons

#include
#define endl '\n'
#define int long long
using namespace std;
int n;
void solve() {
	cin>>n;
	set<int>s;
	for(int i=0;i<n;i++){
		int x,y;
		cin>>x>>y;
		if(x<0) s.insert(1);
		if(x>0) s.insert(2);
		if(y<0) s.insert(3);
		if(y>0) s.insert(4);
	}
	if(s.size()<4) cout<<"Yes"<<endl;
	else if(s.size()==4) cout<<"No"<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

B. Make Almost Equal With Mod
长度为n的数组a,所有数不同
操作:对于所有数,对k取模(总是存在一个k在[1,1e8]使得最终只剩刚好两个数不同)
必须有且仅有一次
输出k

与顺序无关,先排个序
如果有奇数,有偶数,那么k为2
如果全是偶数,那么k可能为4
如果全是奇数,那么k可能为4

通过手玩,发现答案为2的幂次,一开始是想着如果有奇数和偶数的话,那么2即可,然后如果全是偶数的话,然后如果有相差2的偶数,那么4即可,后面如果有相差6的偶数,那么8即可,于是进行推广,2的幂次

证明:将十进制转化为二进制,对2取模即为最后一位,对4取模即为最后两位,…从最低位开始看,如果存在两个数某一位不一样(0和1不一样),假设是第x位,那么模 2 x − 1 2^{x-1} 2x1即可,所以这样是必定可以有解的,因为题目说必然存在解,所以不可能所有数都相同

trick:

将十进制转化为二进制,对2取模即为最后一位,对4取模即为最后两位…

#include
#define endl '\n'
#define int long long
#define INF 1e18
using namespace std;
const int N=110;
int a[N];
int n;
void solve() {
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	set<int>s;
	for(int i=1;i<=n;i++){
		s.insert(a[i]%2);
	}
	if(s.size()==2){
		cout<<2<<endl;
		return;
	}
	for(int i=4;i<=INF;i*=2){
		s.clear();
		for(int j=1;j<=n;j++){
			s.insert(a[j]%i);
		}
		if(s.size()==2){
			cout<<i<<endl;
			return;
		}
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

C. Heavy Intervals
一共有n个区间,第i个区间的单位长度权重为ci
操作:重新排列l,r,c
求所有区间权重之和最小是多少

可以得到所有区间长度和是一定的,然后n个区间的单位长度权重也是一定的,所以就是对一整段长度一定的区间进行分割,给予其不同的单位权重,使得总权重最小,那么就要让平均权重最小,将更小的单位权重给更长的区间,这样可以让平均权值最小

所以就是每次选取当前最短的区间,做法是先将l升序,将r放在set中,对于最大的l,在set中进行二分找到大于它的第一个,构成的区间即为最短的区间,然后在set中删除该元素

区间长度升序,然后权重降序,相乘并相加

trick:
1.找到什么是一定的,这个很重要,往往是解题的关键,比如区间总长度一定,要使得总权重最小,那么就要让平均权重最小

2.在set中进行二分,s.upper_bound(x)表示set中大于x的第一个元素,返回其迭代器

3.set删除元素

erase(iterator) ,删除定位器iterator指向的值

erase(key_value),删除键值key_value的值

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=1e5+10;
int l[N];
int c[N];
int n;
void solve() {
	cin>>n;
	for(int i=0;i<n;i++) cin>>l[i];
	set<int>s;
	for(int i=0;i<n;i++) {
		int x;
		cin>>x;
		s.insert(x);
	}
	for(int i=0;i<n;i++) cin>>c[i];
	sort(l,l+n);
	sort(c,c+n);
	reverse(c,c+n);
	vector<int>ans;
	for(int i=n-1;i>=0;i--){
		auto it=s.upper_bound(l[i]);//在set中找到大于l[i]的第一个元素,返回其迭代器
		int r=*it;
		ans.push_back(r-l[i]);
		s.erase(it);
	}
	sort(ans.begin(),ans.end());
	int res=0;
	for(int i=0;i<n;i++){
		res+=c[i]*ans[i];
	}
	cout<<res<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

你可能感兴趣的:(codeforces,算法,c++)