• #周测10 —— 队列安排、序列合并、扫描、约瑟夫问题


    队列安排

    题目链接
    感谢这位大佬的博客
    以及这位
    以下是 我的笔记

    1. 首先,这道题是对一个数列进行频繁的插入和删除操作,这和链表正好是吻合的,是用链表来做无疑了。
      (可是我当时并没有想到,还是经验太少了)
    2. 明白要用链表来做之后,我打算用STL中的List来做。
    3. 那么就会用到很多前置知识,我唯独缺少了这个:
      list.insert(it, n)可以返回n插入后所在位置上的迭代器。
      什么意思呢?
    • 迭代器:可以理解为用于访问STL容器上某一个元素的一种指针。
      那么pos = list.insert(it, n)就可以用pos得到n被插入后所在位置的指针。
      换句话来说,就是用pos指向n被插入后所在位置
      这道题可以这样操作:
    • 定义一个迭代器数组pos[N],里面用来储存 1到n 所在位置的迭代器;
      也就是用pos[N]指向1到n所有元素在List上的位置。
    • 这样写:pos[n] = list.insert(it, n);;pos[n]就会 得到 以迭代器的类型 返回 n被插入位置上的迭代器。.
      也就是pos[n]会指向n在List上的位置!!
      这样的话就可以用pos[n]直接访问n在List的位置,进行插入和删除操作。
    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e6 + 10; 
    list<int>s;
    list<int>::iterator pos[N];
    list<int>::iterator it;
    //用来判断当前元素是否在 list 内 
    bool st[N];
    int main(){
    //	freopen("ttt.in", "r", stdin);
    //	freopen("ttt.out", "w", stdout);
    	memset(st, 1, sizeof(st));
    	s.push_back(1);
    	pos[1] = s.begin();
    	int n; cin >> n;
    	for(int i = 2; i <= n; i ++){
    		int a, b;
    		scanf("%d%d", &a, &b);
    		it = pos[a];
    		//右边 ,否则左边 
    		if(b) it ++;
    		//插入 
    		pos[i] = s.insert(it, i);
    	}
    	
    	int m; cin >> m;
    	for(int i = 1; i <= m; i ++){
    		//输入要出来的元素 
    		int a; cin >> a;
    		//如果这个元素还在List里面 
    		if(st[a]){
    			//用于删除某节点 
    			s.erase(pos[a]);
    			st[a] = 0; 
    		}
    		
    	}
    
    	for(it = s.begin(); it != s.end(); it ++)
    		printf("%d ", *it);
    	puts("");
    	return 0;
    }
    /*
    这是find(),可以直接找到n的位置
    //	d.push_back(1);
    //	d.push_back(3);  
    //	it = find (d.begin(), d.end(), 9);
    	it --;
    	printf("%d ", *it);
    //	cout << *it;
    */
    
    

    序列合并

    题目

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 10;
    //大根堆 
    priority_queue<int>q;
    int a[N], b[N], ans[N];
    int main(){
    	int n;
    	//题目说了这里是严格递增的,我们就不需要额外排序了 
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
        for(int i = 1; i <= n; i ++) scanf("%d", &b[i]);
        
        for(int i = 1; i <= n; i ++){//a的迭代器 
            for(int j = 1; j <= n; j ++){//b的迭代器 
                int sum = a[i] + b[j];
                //一旦还不够就先加入 
                if(q.size() < n) q.push(sum);
                else{
                	//够了的话 ,就只要把那些比当前最大的数要小的放进来就好了
                    if(q.top() > sum){
                        q.pop();
                        q.push(sum);
                    }
                    //如果不满足条件就说明这个元素比当前所有的元素都要大,不管他 
                    //这里的break是对j的循环生效的,
    				//也就是说,当前i的情况下再去遍历后面的j已经没有意义了
    				//因为b数组时单调递增的,后面的数也是铁定大于当前a[i] + b[j]的,一定是会被淘汰的。 
    				//于是开始下一个i
    				//到后面基本上是不会进行什么操作了的,因此实际时间应该非常低才对。 
                    else break;  
                }
            }
        }
        //反向输出 
        for(int i = n; i >= 1; i --){
            ans[i] = q.top();
            q.pop();
        }
        for(int i = 1;i <= n; i ++) printf("%d ",ans[i]);
        return 0;
    }
    
    
    
    

    扫描

    题目链接
    不多解释了,这就是低配的滑动窗口嘛,老熟悉了我……
    就当是第五刷了。前四刷链接

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 3e6 + 10;
    deque<int>q;
    int a[N];
    int main(){
    	int n, k;
    	cin >> n >> k;
    	for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    	for(int i = 1; i <= n; i ++){
    		//首先当然是维护队列的单调性啦! 
    		while(!q.empty() && a[i] > a[q.back()]) q.pop_back();
    		if(!q.empty() && q.front() < i - k + 1) q.pop_front();
    		q.push_back(i);
    		if(i >= k) printf("%d
    ", a[q.front()] );
    	}
    	return 0;
    }
    

    约瑟夫问题

    链接

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    	vector<int>table;//定义一个数组模拟圆桌
    	int n,m;
    	cin >> n >> m;
    	for(int i = 1; i <= n; i ++) table.push_back(i);
    	//如果还没空掉那就操作 
    	//一开始的指针位置,从0开始数数 
    	int pos = 0;
    	while(!table.empty()){
    		//首先是找到当前的指针位置 (以确定删除的位置)
    		 pos = (pos + m - 1) % table.size();
    		 //将其输出 
    		 printf("%d ", table[pos]);
    		 //出队 
    		 table.erase(table.begin() + pos);
    	}
    	return 0; 
    }
    
  • 相关阅读:
    Nilearn教程系列(2)-3D和4D niimgs:处理和可视化
    Python-EEG工具库MNE中文教程(9)-参考电极应用
    EEMD算法原理与python实现
    Python-EEG工具库MNE中文教程(8)-参考电极简介
    联想笔记本 thinkpad BIOS 超级密码 Supervisor Password 清除 破解 亲测有效 转载地址https://blog.csdn.net/ot512csdn/article/details/72571674
    C Primer Plus 学习 第四章
    C Primer Plus 学习 第三章
    六 BASH 高级变量
    五 shell 变量与字符串操作
    四 shell基本命令
  • 原文地址:https://www.cnblogs.com/yuanyulin/p/14026709.html
Copyright © 2020-2023  润新知