ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

1-stl介绍_题解

2022-07-04 15:05:39  阅读:161  来源: 互联网

标签:set cout stl 题解 rep cin 介绍 int solve


1-stl介绍_题解

2022/7/4-ACM暑期集训

A,最大或位_位运算贪心

题目大意

中文题自己看

思路和代码

要xy的或值最大则尽量让每一位或的结果都是1。考虑将y固定在r,x从l一点点变大。所以我们要让x在不大于r的情况下尽可能大。从大往小考虑二进制位。一旦出现“1<->0”的情况就表示后面可以全1(因为x不可能比y大了)。

void solve(){
	ll l , r ;
	cin >> l >> r ;

	ll ans = 0 ;
	drep(i , 0 , 63){
		if(r >> i & 1){
			ans |= (1ll << i) ;
			if(!(l >> i & 1)){
				ans += (1ll << i) - 1 ;
				break ;
			}
		}
	}
	cout << ans << "\n" ;
	
}//code_by_tyrii 

当然,这题放在STL专题里是为了介绍bitset的,但是bitset我感觉没什么用,都可以用位运算解决。

下面给出bitset的做法

void solve(){
	ll l , r ;
	cin >> l >> r ;
	bitset<64> a(l) , b(r) ;
	
	int p = 63 ;
	while(p >= 0 && a[p] == b[p]) p -- ;
	while(p >= 0) a[p -- ] = 1 ;
	ll ans = 0 ;
	rep(i , 0 , 63)
        ans |= (1ll << i) * a[i] ;
	cout << ans << '\n' ;
	
}//code_by_tyrii 

B,水果_二维map

题目大意

中文题目自己看

思路和代码

hdu老题,注意格式。

是一个二维的矩阵,xy轴分别是产地和品种。这样直接就可以得到数值。所以就做一个二维的map即可。要注意的是,map是一棵树,二维的map就是树的每个节点都是一棵树。但是我们用的时候直接简单理解成二维的矩阵即可。

void solve(){
	cin >> n ;
	map<string , map<string , int> > mp ;
	
	rep(i , 1 , n){
		string s , t ;
		int num ;
		cin >> s >> t >> num ;
		mp[t][s] += num ;
		
	} 
	map<string , map<string , int> >:: iterator it ;
	for(it = mp.begin() ; it != mp.end() ; it ++ ){
		cout << (*it).fi << "\n" ;
		map<string , int>::iterator it2 ;
		for(it2 = ((*it).se).begin() ; it2 != ((*it).se).end() ; it2 ++ ){
			cout << "   |----" << (*it2).fi << "(" << (*it2).se << ")\n" ;
		}
		
	}
	
}//code_by_tyrii 

C,Bombing_map+mset

题目大意

在一个二维平面上有n个敌军基地,现在要轰炸他们。每次可以轰炸所有水平或者竖直的敌人。问每次轰炸会摧毁几个敌军基地。(已经被摧毁的基地不能再被摧毁)

思路和代码

朴素做法直接开一个二维地图一点点炸,不过这样时空复杂度都会炸。

考虑横纵坐标分开考虑(坐标范围达到1e9基本上都是这样的做法)。对每一行每一列分别维护一个multiset表示每行中的列坐标和每列中的行坐标。

这样的话相当于对整个地图进行了离散化所以降低了空间复杂度。并且对点的删除操作可以达到O(n(log(logn)))。

int n , m , k ; 

void solve(){
	map<int , multiset<int> > mp[2] ;

	rep(i , 1 , n){
		int x , y ; cin >> x >> y ;
		mp[0][x].insert(y) ;
		mp[1][y].insert(x) ;
	}
	while(m -- ){
		int dir , k ; cin >> dir >> k ;
		cout << mp[dir][k].size() << "\n" ;
		for(auto it : mp[dir][k]){
			//(k , it)
			mp[dir^1][it].erase(k) ;
		}
		mp[dir][k].clear() ;
	}
	cout << "\n" ;
	
}//code_by_tyrii 

int main(){
	
	ios::sync_with_stdio(false) ;
//	cin.tie(0) ; cout.tie(0) ;
	ll T ; 
	while(1){
		cin >> n >> m ;
		if(!n && !m) break ;
		solve() ; 
	}
	
}

D,人见人爱A-B_set

题目大意

中自看

思路和代码

基础set的使用

void solve(){
	while(1){
		cin >> n >> m ;
		if(!n && !m) return ;
		set<int> st ;
		rep(i , 1 , n){
			int tmp ; cin >> tmp ;
			st.insert(tmp) ;
		}
		rep(i , 1 , m){
			int tmp ; cin >> tmp ;
			if(st.size())
			st.erase(tmp) ;
		}
		if(!st.size()) cout << "NULL" ;
		else for(auto it : st)
		cout << it << " " ; cout << "\n" ;
	}
}//code_by_tyrii 

E,Column Swapping_set

题目大意

给二维数组,现在可以交换任意两列,问是否可能使得每一行都非降序

思路和代码

找到每一行里需要被交换的元素,将其横坐标丢到set里面,由于set的插入是自己去重的所以比较方便。

void solve(){
	cin >> n >> m ;
	vct<vct<int> > a(n + 1 , vct<int>(m + 1 , 0)) ;
	rep(i , 1 , n) 
	rep(j , 1 , m)
	cin >> a[i][j] ;
	
	auto b = a ;
	
	rep(i , 1 , n)
	sort(b[i].begin() + 1 , b[i].end()) ; 
	
	set<int> st ;
	
	rep(i , 1 , n)
	rep(j , 1 , m)
	if(a[i][j] != b[i][j]) st.insert(j) ;
	
	if(st.size() > 2) cout << "-1\n" ;
	else if(!st.size()) cout << "1 1\n" ;
	else{
		int l = *st.begin() , r = *st.rbegin() ;
		rep(i , 1 , n){
			swap(a[i][l] , a[i][r]) ;
			rep(j , 2 , m)
			if(a[i][j - 1] > a[i][j]){
				cout << "-1\n" ; return ;
			}
		}
		cout << l << " " << r << "\n" ;
	}
	
}//code_by_tyrii 

F,看病要排队_PQ重载运算符

题目大意

中自看

思路和代码

每个医生做一个优先队列,重载小于号之后简单的入队出队即可

struct Node{
	int num , imp ;
	friend bool operator <( const Node &u , const Node &v){
		if(u.imp == v.imp) return u.num > v.num ;
		return u.imp < v.imp ;
	}
};
int n ;
void solve(){
//	cin >> n ;
	priority_queue<Node> q[4] ;
	int cnt = 0 ;
	while(n -- ){
		string op ; cin >> op ;
		int doc , x ;
		cin >> doc ;
		if(op == "IN"){
			cin >> x ;
			Node tmp = { ++ cnt , x} ;
			q[doc].push(tmp) ;
		}else{
			if(q[doc].size()){
				cout << q[doc].top().num << "\n" ;
				q[doc].pop() ;
			}else cout << "EMPTY\n" ;
		}
	}
	
}//code_by_tyrii 

int main(){

	ios::sync_with_stdio(false) ;

	while(cin >> n)
	solve() ;
	
}

G,awoo's Favorite Problem_PQ

题目大意

给字符串s和t。现有两种操作,操作1使“ab”变成“ba”,操作2使“bc”变成“cb”。问经过若干次操作后s有无可能变成t。

思路和代码

将两个字符串一位一位进行匹配。然后就有四种情况:

  • s_i==t_i 则匹配
  • s_i == 'a' and t_i == 'b' 则表明i位置的b需要从[i,n]中的某个位置(假设是j)移动而来。考虑要从j一路移到i,则表明[i,j]中没有字符c(不然就断掉了)。而可以贪心的想到,j位置就是[i,n]区间中字符b的第一次出现位置。
  • s_i == 'b' and t_i == 'c' 和上一种情况类似。
  • else

那么考虑如何编码:

做三个set,表示abc三种字符在[i,n]区间中的下标序列。然后两个字符串一位一位的对齐匹配,出现不匹配情况就尝试去将ti移动到si位置。总体是一个模拟的思路。

string solve2(){
	
	cin >> n ;
	string s , t ;
	cin >> s >> t ;
	s = " " + s ;
	t = " " + t ;
	
	set<ll> idx[3] ;
	rep(i , 1 , n)
	idx[s[i] - 'a'].insert(i) ;
	
	//[i,n]的abc三种字母的升序下标序列 
	
	rep(i , 1 , n){
//		cout << i << "=>" << s << "\n" ;
		if(s[i] == t[i]){//直接匹配 
			idx[s[i] - 'a'].erase(i) ;
			continue ;
		}
		if(s[i] == 'a' && t[i] == 'b'){
			//aaab 后面的b移到i位置 
			//baaa
			if(!idx[1].size()) return "NO\n" ;//没有b可以换到i位置 
			int posb = *idx[1].begin() ;
			int posc = *idx[2].begin() ;
			if(idx[2].size() && posc < posb) return "NO\n" ;
			idx[0].erase(i) ;
			idx[1].erase(posb) ;
			idx[0].insert(posb) ;
			swap(s[i] , s[posb]) ;
//			cout << i << " <- " << posb << "\n" ;
			continue ;
		}
		if(s[i] == 'b' && t[i] == 'c'){
			//bbbc
			//cbbb
			if(!idx[2].size()) return "NO\n" ; 
			int posc = *idx[2].begin() ;
			int posa = *idx[0].begin() ;
			if(idx[0].size() && posa < posc) return "NO\n" ;
			idx[1].erase(i) ;
			idx[2].erase(posc) ;
			idx[1].insert(posc) ;
			swap(s[i] , s[posc]) ;
			continue ;
		}
		return "NO\n" ;
	}
	return "YES\n" ;
}

接下来是堆的解法:

仔细思索一下整个解题步骤:

遇到不匹配的时候尝试从后面换一个匹配的字符过来。而这个交换就是在字符的下标序列里面插入一个新的点。而每次交换的时候,换过来的字符肯定是所有同种字符里的第一个。就是每次取头,再插入。所以优先队列完美胜任。要注意在交换的时候对堆的维护,细节写在代码里了。

string solve3(){
	string s , t ;
	cin >> n >> s >> t ;
	
	s = " " + s ;
	t = " " + t ;
	
	priority_queue<ll , vct<ll> , greater<ll> > idx[3] ;
	
	rep(i , 1 , n) idx[s[i] - 'a'].push(i) ;
	
	rep(i , 1 , n){
//		cout << i << " " << s << "\n" ;
		if(s[i] == t[i]){
//			cout << idx[s[i] - 'a'].top() << "\n" ;
			idx[s[i] - 'a'].pop() ;
			continue ;
		}
		if(s[i] == 'a' && t[i] == 'b'){
			if(!idx[1].size()) return "NO\n" ;//后面没有b可以交换到第i位
			int posb = idx[1].top() ;
			if(idx[2].size()){
				int posc = idx[2].top() ;
				if(posc < posb) return "NO\n" ;//中间被c截断了,b移不到i位置
			}
//			cout << idx[s[i] - 'a'].top() << "\n" ;
			idx[s[i] - 'a'].pop() ;
			swap(s[i] , s[posb]) ;//交换 
			idx[1].pop() ;
			idx[0].push(posb) ; 
			continue ;
		}
		if(s[i] == 'b' && t[i] == 'c'){
			if(!idx[2].size()) return "NO\n" ;//后面没有c可以交换到第i位
			int posc = idx[2].top() ;
			if(idx[0].size()){
				int posa = idx[0].top() ;
				if(posa < posc) return "NO\n" ;//中间被a截断了,c移不到i位置
			}
//			cout << idx[s[i] - 'a'].top() << "\n" ;
			idx[s[i] - 'a'].pop() ;
			swap(s[i] , s[posc]) ;//交换 
			idx[2].pop() ;
			idx[1].push(posc) ; 
			continue ;
		}
		return "NO\n" ;
	}
	return "YES\n" ;
}

H,Alice and the Cake_思维-堆

题目大意:

一个蛋糕每次可以切一半,如12切成6+6,13切成6+7。现在给一堆无序的数,问是否可能由一个蛋糕切割得来。

思路和代码:

模拟切蛋糕的过程,并且每次切完贪心的去比较切出来的最大蛋糕和给出的最大蛋糕是否匹配。若不匹配就再去切即可。

 
string solve2(){
	int n ; 
	cin >> n ;
	vct<ll> a(n + 1 , 0) ;
	priority_queue<ll , vct<ll> , less<ll> > now , q ;
	
	rep(i , 1 , n) cin >> a[i] , q.push(a[i]) ;
	
	ll sum = accumulate(a.begin() + 1 , a.end() , 0LL) ;
	
	now.push(sum) ;
	ll cnt = 0 ;
	while(q.size() && now.size()){
		ll ma = remain.top() ;
		now.pop() ;
//		cout << ma << " " << q.top() << "\n";
		if(ma == q.top()){
			q.pop() ;
		}else{
//			cout << cnt + 1 << "<\n" ;
			if(++ cnt > n - 1) return "NO\n" ;
			now.push(ma / 2) ;
			now.push(ma / 2 + (ma % 2 ? 1 : 0)) ;
			
		}
	}
	return "YES\n" ;
}

标签:set,cout,stl,题解,rep,cin,介绍,int,solve
来源: https://www.cnblogs.com/tyriis/p/16442911.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有