7.12集训总结

昨天感觉效率也不是很高,可能我效率从来没很高过吧。可能一直在分神

昨天还是做的线性表,做了一天可算做完了!!

P1996 约瑟夫问题

这题看了标签之后才开始做的,看见是队列然后思路马上就有了。开2个队列来回就行。

其他做法:链表。

还是一样模拟,注意stl中end(),是不存在的!!!

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}

	ll d=ex_gcd(b,a%b,y,x);
	y=y-a/b*x;
	return d;
}
list<ll>s;
int n,m;
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		s.push_back(i);
	}
	list<ll>::iterator it=s.begin();
	
	while(s.size()>1){
		for(int i=1;i<m;i++){
			it++;
			if(it==s.end())it=s.begin();
		}
		
		cout<<*it<<" ";
		it++;
		list<ll>::iterator node=it;
		if(node==s.end())node=s.begin();
		s.erase(--it);
		it=node;
	}
	cout<<*it<<endl;


	return 0;
}

P1160 队列安排

频繁的填数和删除好像可以用列表吧。

填数如下操作

设一个迭代器数组

next()是求迭代器的下一个,而迭代器本身的位置不会变

list <ll>::iterator pos[100005];
for(int i=2;i<=n;i++){
		cin>>k>>p;
		if(p==0){
			pos[i]=s.insert(pos[k],i);
		}else{
			list<ll>::iterator it=next(pos[k]);
			pos[i]=s.insert(it,i);
		}
	}

删除数据

删除数组最好用erase,不要用remove,因为remove不是真正的删除,而是将要删除的数据放在最后了

for(int i=1;i<=m;i++){
		ll x;
		cin>>x;
		if(vis[x]==1){
			continue;
		}else{
			s.erase(pos[x]);
			vis[x]=1;
		}
		
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include<list>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}

	ll d=ex_gcd(b,a%b,y,x);
	y=y-a/b*x;
	return d;
}
int n,k,p,m;
list<ll>s;
list <ll>::iterator pos[100005];
bool vis[100005];
int main(){
	cin>>n;
	s.push_back(1);	
	pos[1]=s.begin();
	
	for(int i=2;i<=n;i++){
		cin>>k>>p;
		if(p==0){
			pos[i]=s.insert(pos[k],i);
		}else{
			list<ll>::iterator it=next(pos[k]);
			pos[i]=s.insert(it,i);
		}
	}
	cin>>m;
	for(int i=1;i<=m;i++){
		ll x;
		cin>>x;
		if(vis[x]==1){
			continue;
		}else{
			s.erase(pos[x]);
			vis[x]=1;
		}
		
	}
	list<ll>::iterator it;
	for(it=s.begin();it!=s.end();++it){
		cout<<*it<<" ";
	}

	return 0;
}

P2058 [NOIP2016 普及组] 海港

这题一直没搞懂怎么搞那个国家的人数,想过前缀和,但不行..

正确做法:

开一个vis[]数组来记录各个国家的人数,开一个结构体来记录国家和时间,

用队列存储每一艘船的信息:国家和时间

如果队列的时间不在24小时内,对vis数组更新,如果更新后vis[]=0,ans--

然后pop(),continue;如果满足条件就break;

入队列同理

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}

	ll d=ex_gcd(b,a%b,y,x);
	y=y-a/b*x;
	return d;
}
struct Node{
	ll nation,time;
}u; 
int n,k,t;
ll vis[100005];
ll ans=0;
queue<Node>q;
int main(){
	cin>>n;
	
	for(int i=1;i<=n;i++){
		
		cin>>t>>k;
		
		while(!q.empty()){
			u=q.front();
			
			if(t-u.time>=86400){
				q.pop();
				vis[u.nation]--;
				if(vis[u.nation]==0)ans--;
				continue;				
			}else{
				break;
			}
		}
		
		for(int j=1;j<=k;j++){
			int x;
			scanf("%d",&x);
			u.nation=x;
			u.time=t;
			if(vis[x]==0)ans++;
			vis[x]++;
			q.push(u);
			
		}
		
		printf("%lld\n",ans);
		
	}


	return 0;
}

P2234 [HNOI2002] 营业额统计

一道绿题,但是暴力可以过...

正确做法:二分+set

在次之前我还不知道set可以二分...

k为迭代器,s为set、

k=s.lower_bound(x);

这题还有一点很妙的是,提前存入1个正的大数和负的大数

防止lower_bound()没有搜到,或者搜到的第一个位置为1

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}

	ll d=ex_gcd(b,a%b,y,x);
	y=y-a/b*x;
	return d;
}
set<ll>s;
int n;
set<ll>::iterator a,k;
int main(){
	
	ll x;
	s.insert(192608170);
	s.insert(-192608170);
	cin>>n;
	
	ll ans=0;
	
	for(int i=1;i<=n;i++){
			cin>>x;
			if(i==1){
				ans=ans+x;
				s.insert(x);
			}else{
				
				k=s.lower_bound(x);
				if(*k!=x){
				
					a=k;
					--a;
					ans=ans+min(abs(*a-x),abs(*k-x));
					s.insert(x);
				
			}
		}
	}
	
	cout<<ans;
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值