zoukankan      html  css  js  c++  java
  • CSUOJ 1982 小M的移动硬盘

    Description

    最近小M买了一个移动硬盘来储存自己电脑里不常用的文件。但是他把这些文件一股脑丢进移动硬盘后,觉得这些文件似乎没有被很好地归类,这样以后找起来岂不是会非常麻烦?
    小M最终决定要把这些文件好好归类,把同一类地移动到一起。所以现在小M有了这几种操作:
    1 u 表示把编号为u的文件放到最上面
    2 u 表示把编号为u的文件放到最下面
    3 u v 表示把编号为u的文件放到编号为v的文件的后面
    已知在最开始的时候,1号文件到n号文件从上往下排布
    现在小M已经给出了他所进行的所有操作,你能告诉他操作之后的序列是会变成什么样子吗?

    Input

    第一行为一个数字T(T<=10)表示数据组数
    第二行为两个数字n、m(1<=n,m<=300000)表示序列长度和小M的操作次数
    接下来m行每行两个或三个数字,具体含义见题面
    保证数据合法

    Output

    输出一行表示小M操作结束后的序列

    Sample Input

    1
    10 5
    1 5
    2 3
    2 6
    3 4 8
    3 1 3

    Sample Output

    5 2 7 8 4 9 10 3 1 6

    Hint

    这道题之前见过好几次,没有一次写出来过,前几天认真研究了一下,终于写出来了。
    思路:对每个位置,用l 和r两个数组记录该位置前面和后面的数的编号,每次变动的时候更新一下就好了。
    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    #define MAXN 300010
    typedef long long ll;
    int m, n;
    int l[MAXN], r[MAXN];
    void init()
    {
    	r[0] = 1;
    	l[n + 1] = n;
    	for (int i = 1; i <= n; i++)
    	{
    		l[i] = i - 1;
    		r[i] = i + 1;
    	}
    }
    void con(int x, int y)
    {
    	r[x] = y;
    	l[y] = x;
    }
    int main()
    {
    	int T,x,u,v;
    	while (cin >> T)
    	{
    		while (T--)
    		{
    			cin >> n >> m;
    			init();
    			for (int i = 0; i < m; i++)
    			{
    				cin >> x;
    				if (x == 1)
    				{
    					cin >> u;
    					if (r[0] == u)
    						continue;
    					int l_u = l[u],r_u=r[u],r0=r[0];
    					con(l_u, r_u);
    					con(u, r0);
    					con(0, u);
    				}
    				else if (x == 2)
    				{
    					cin >> u;
    					if (l[n+1] == u)
    						continue;
    					int l_u = l[u], r_u = r[u], l_n = l[n+1];
    					con(l_u, r_u);
    					con(l_n, u);
    					con(u, n+1);
    				}
    				else
    				{
    					cin >> u >> v;
    					if (r[v] == u)
    						continue;
    					int l_u = l[u], r_u = r[u], r_v = r[v];
    					con(l_u, r_u);
    					con(u, r_v);
    					con(v, u);
    				}
    			}
    			int temp = r[0];
    			cout << temp;
    			while (r[temp] != (n + 1))
    			{
    				cout << " " << r[temp];
    				temp = r[temp];
    			}
    			cout << endl;
    		}
    	}
    	return 0;
    }
    /**********************************************************************
    	Problem: 1982
    	User: leo6033
    	Language: C++
    	Result: AC
    	Time:984 ms
    	Memory:4368 kb
    **********************************************************************/
    
    这题还能用链表来写,可以自己思考思考


  • 相关阅读:
    241. Different Ways to Add Parentheses java solutions
    89. Gray Code java solutions
    367. Valid Perfect Square java solutions
    46. Permutations java solutions
    116. Populating Next Right Pointers in Each Node java solutions
    153. Find Minimum in Rotated Sorted Array java solutions
    判断两颗树是否相同
    求二叉树叶子节点的个数
    求二叉树第k层的结点个数
    将二叉排序树转换成排序的双向链表
  • 原文地址:https://www.cnblogs.com/csu-lmw/p/9124430.html
Copyright © 2011-2022 走看看