【算法竞赛入门经典】第五章

题目链接:https://vjudge.net/contest/216713

两个月前,也就是寒假做的题。

据说是用来熟悉STL的水题,然而不熟练STL的我做得好艰难啊。

只按照书上的最低要求选做了一些,其他实在是懒得做…


例题5-1

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

const int maxn = 10000 + 10;
int a[maxn];

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	int n, q, kase = 0;
	while(scanf("%d%d", &n, &q) && n && q)
	{
		printf("CASE# %d:\n", ++kase);
		for(int i = 0; i < n; i++)
			scanf("%d", &a[i]);
		sort(a, a + n);
		int x, flag;
		for(int i = 0; i < q; i++)
		{
			scanf("%d", &x);
			flag = 0;
			for(int j = 0; j < n; j++)
			{
				if(a[j] == x)
				{
					flag = 1;
					printf("%d found at %d\n", x, j + 1);
					break;
				}
			}
			if(!flag)
				printf("%d not found\n", x);
		}			
	}
    return 0;
}

例题5-2

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
	vector<int> v[]相当于二维数组,
	它的第一维大小固定,第二维大小不固定;
	题目有四个指令,善于寻找他们的共同点
*/

vector<int> v[30];
int n;

//寻找x木块所在堆和高度,用引用返回
void Find(int x, int &p, int &h)
{
	for(p = 0; p < n; p++)
		for(h = 0; h < v[p].size(); h++)
			if(v[p][h] == x)
				return;
}

//把x木块上面的木块归位,resize
void POP(int x, int p, int h)
{
	for(int i = h + 1; i < v[p].size(); i++)
	{
		int x = v[p][i];
		v[x].push_back(x);
	}
	v[p].resize(h + 1);
}

//把a及上方木块移动到b上方
void Move(int a, int b, int pa, int ha, int pb, int hb)
{
	for(int i = ha; i < v[pa].size(); i++)
	{
		int x = v[pa][i];
		v[pb].push_back(x);
	}
	v[pa].resize(ha);
}

void Print()
{
	for(int i = 0; i < n; i++)
	{
		cout << i << ':';
		for(int j = 0; j < v[i].size(); j++)
			cout << ' ' << v[i][j];
		cout << '\n';
	}
}

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	cin >> n;
	for(int i = 0; i < n; i++)
		v[i].push_back(i);
	string s1, s2;
	int a, b;
	while(cin >> s1 >> a >> s2 >> b)
	{
		int pa, ha, pb, hb;
		Find(a, pa, ha);
		Find(b, pb, hb);
		if(pa == pb || a == b)
			continue;
		if(s2 == "onto")
			POP(b, pb, hb);
		if(s1 == "move")
			POP(a, pa, ha);
		Move(a, b, pa, ha, pb, hb);
	}
	Print();
    return 0;
}

例题5-3

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
    学会使用stringstream,迭代器iterator和set;
    set中各个元素不重复且有序
*/

set<string> S;

int main()
{
//  freopen("input.txt", "r", stdin);
//  freopen("output.txt", "w", stdout);
    string s, a;
    while(cin >> s)
    {
        for(int i = 0; i < s.length(); i++)
        {
            if(isalpha(s[i]))
            {
                if(s[i] >= 'A' && s[i] <= 'Z')
                    s[i] = s[i] + 32;
               // s[i] = tolower(s[i]);
            }
            else
                s[i] = ' ';
        }
        stringstream ss(s);
        while(ss >> a)
        {
            S.insert(a);
        }
    }
    set<string>::iterator it;
    for(it = S.begin(); it != S.end(); it++)
        cout << *it << '\n';
    return 0;
}

例题5-4

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
    开两个vector存原始单词和转换成小写后的单词;
    map可以计数
*/

vector<string> words;
vector<string> ans;
map<string, int> num;

string tra(string s)
{
    string ans = s;
    for(int i = 0; i < ans.length(); i++)
        ans[i] = tolower(ans[i]);
    sort(ans.begin(), ans.end());
    return ans;
}

int main()
{
//  freopen("input.txt", "r", stdin);
//  freopen("output.txt", "w", stdout);
    string s, a;
    while(cin >> s && s != "#")
    {
        words.push_back(s);
        a = tra(s);
        if(!num.count(a))
            num[a] = 0;
        num[a]++;
    }
    for(int i = 0; i < words.size(); i++)
    {
        if(num[tra(words[i])] == 1)
            ans.push_back(words[i]);
    }
    sort(ans.begin(), ans.end());
    for(int i = 0; i < ans.size(); i++)
        cout << ans[i] << '\n';
    return 0;
}

例题5-5

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
    关键:
        set<int> Set;
        map<Set, int> ID;
        vector<Set> SET;
    对于每一个Set s,
    ID[s]是ID,SET[ID[s]]是s本身。
*/

typedef set<int> Set;
map<Set, int> ID;
vector<Set> SET;

int Search(Set s)
{
    if(!ID.count(s))
    {
        SET.push_back(s);
        ID[s] = SET.size() - 1;
    }
    return ID[s];
}

int main()
{
//  freopen("input.txt", "r", stdin);
//  freopen("output.txt", "w", stdout);
    int T, n;
    scanf("%d", &T);
    while(T--)
    {
        stack<int> s;
        scanf("%d", &n);
        while(n--)
        {
            string p;
            cin >> p;
            if(p[0] == 'P')
                s.push(Search(Set()));
            else if(p[0] == 'D')
                s.push(s.top());
            else
            {
                Set x1 = SET[s.top()];
                s.pop();
                Set x2 = SET[s.top()];
                s.pop();
                Set x;
                if(p[0] == 'U')
                    set_union(x1.begin(), x1.end(), x2.begin(), x2.end(), inserter(x, x.begin()));
                else if(p[0] == 'I')
                    set_intersection(x1.begin(), x1.end(), x2.begin(), x2.end(), inserter(x, x.begin()));
                else
                {
                    x = x2;
                    x.insert(Search(x1));
                }
                s.push(Search(x));
            }
            cout << SET[s.top()].size() << '\n';
        }
        cout << "***" << '\n';
    }
    return 0;
}

例题5-6

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
    要弄清题意
*/

int main()
{
//  freopen("input.txt", "r", stdin);
//  freopen("output.txt", "w", stdout);
    int T, kase = 1;
    while(scanf("%d", &T) && T)
    {
        queue<int> Q;
        queue<int> q[1010];
        map<int, int> M;
        for(int i = 0; i < T; i++)
        {
            int n;
            scanf("%d", &n);
            while(n--)
            {
                int x;
                scanf("%d", &x);
                M[x] = i;
            }
        }

        printf("Scenario #%d\n", kase++);
        char s[10];
        while(1)
        {
            scanf("%s", s);
            if(s[0] == 'S')
                break;
            else if(s[0] == 'E')
            {
                int x;
                scanf("%d", &x);
                int t = M[x];
                if(q[t].empty())
                    Q.push(t);
                q[t].push(x);
            }
            else
            {
                int t = Q.front();
                printf("%d\n", q[t].front());
                q[t].pop();
                if(q[t].empty())
                    Q.pop();
            }
        }
        printf("\n");
    }
    return 0;
}

例题5-7

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
    priority_queue<ll, vector<ll>, greater<ll> > pq;
    优先队列,越大优先级越小,即从小到大排序。
    若省略最后一个参数,则是从大到小。
*/

int main()
{
//  freopen("input.txt", "r", stdin);
//  freopen("output.txt", "w", stdout);
    priority_queue<ll, vector<ll>, greater<ll> > pq;
    set<ll> S;                  //用于判断是否重复
    pq.push(1);
    S.insert(1);
    for(int i = 1; ; i++)
    {
        ll x = pq.top();
        pq.pop();
        if(i == 1500)
        {
            printf("The 1500'th ugly number is %lld.\n", x);
            break;
        }

        ll y;
        y = 2 * x;
        if(!S.count(y))
        {
            pq.push(y);
            S.insert(y);
        }
        y = 3 * x;
        if(!S.count(y))
        {
            pq.push(y);
            S.insert(y);
        }
        y = 5 * x;
        if(!S.count(y))
        {
            pq.push(y);
            S.insert(y);
        }
    }
    return 0;
}

例题5-8

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
    计算行列,模拟即可
*/

string s[110];
const int maxn = 60;

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
    int n;
    while(cin >> n)
    {
    	int M = 0;
    	for(int i = 0; i < n; i++)
    	{
    		cin >> s[i];
    		M = max(M, (int)s[i].length());
    	}
    	sort(s, s + n);

    	int cols = (60 - M) / (M + 2) + 1;
    	int rows = (n - 1) / cols + 1;

    	for(int i = 0; i < maxn; i++)
    		cout << '-';
    	cout << '\n';
    	for(int i = 0; i < rows; i++)
    	{
    		for(int j = 0; j < cols; j++)
    		{
    			int x = rows * j + i;
    			if(x < n)
    			{
    				int len = s[x].length();
    				cout << s[x];
    				if(j == cols - 1)
    				{
    					for(int k = 0; k < M - len; k++)
    						cout << ' ';
    				}
    				else
    				{
    					for(int k = 0; k < M + 2 - len; k++)
    						cout << ' ';
    				}
    			}
    		}
    		cout << '\n';
    	}
    }
    return 0;
}

例题5-9

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
	直接枚举r1,r2,c1,c2肯定T
	解决方法:
		枚举c1,c2,然后从上到下扫描各行
		把每行c1,c2列的内容存到map中
		若已经存在,则找到
*/

struct Node
{
	int x, y;
	Node(int a, int b)
	{
		x = a;
		y = b;
	}
	bool operator < (const Node & b) const
	{
		if(x == b.x)
			return y < b.y;
		return x < b.x;
	}
};

map<string, int> ID;	//给每个字符串一个编号
vector<string> str;		//保存编号对应的字符串
vector<int> v[10010];	//存处理好的int表格
map<Node, int> M;

int IDD(string s)		//获取编号
{
	if(ID.count(s))
		return ID[s];
	str.push_back(s);
	return ID[s] = str.size() - 1;
}

void solve(int n, int m)
{
	for(int i = 0; i < m; i++)			//i列
	{
		for(int j = i + 1; j < m; j++)	//j列
		{
			M.clear();
			for(int k = 0; k < n; k++)	//k行
			{
				Node node(v[k][i], v[k][j]);
				if(M.count(node))
				{
					printf("NO\n");
					printf("%d %d\n", M[node] + 1, k + 1);
					printf("%d %d\n", i + 1, j + 1);
					return;
				}
				else
				{
					M[node] = k;
				}
			}
		}
	}
	printf("YES\n");
}

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	int n, m;
	while(~scanf("%d%d", &n, &m))
	{
		string s;
		char ch = getchar();
		for(int i = 0; i < n; i++)
		{
			while(1)
			{
				ch = getchar();
 				if(ch == '\n' || ch == '\r')
				{
					if(!s.empty())
						v[i].push_back(IDD(s));
					s.clear();
					break;
				}
				if(ch == ',')
				{
					v[i].push_back(IDD(s));
					s.clear();
				}
				else
				{
					s = s + ch;
				}
			}
		}
		solve(n, m);

		//千万不能忘!!!
		for(int i = 0; i < n; i++)
			v[i].clear();
		ID.clear();
		str.clear();
	}
    return 0;
}

习题5-1

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
	用getline读一行
	用stringstream一个个读入
	注意getline格式
*/

vector<string> v[1010];
int a[200];

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	int i = 0, num = 0;
	string sin;
	while(getline(cin, sin))
	{
		stringstream ss(sin);
		string s;
		while(ss >> s)
			v[i].push_back(s);
		i++;
	}

	//求第k个单词的最大长度存入a[]
	for(int j = 0; j < i; j++)
	{
		for(int k = 0; k < v[j].size(); k++)
		{
			a[k] = max(a[k], (int)v[j][k].length());
			num = max(num, k);
		}
	}

	//输出,注意最后一列不用输出空格
	for(int j = 0; j < i; j++)
	{
		for(int k = 0; k < v[j].size() - 1; k++)
		{
			cout << v[j][k];
			for(int l = 0; l < a[k] - v[j][k].length(); l++)
				cout << ' ';
			cout << ' ';
		}
		cout << v[j][v[j].size() - 1] << '\n';
	}
	return 0;
}

习题5-2

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
	题目保证1000步之内必定变成0或者循环,所以判断0即可
*/

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	int a[2][20];
	int T;
	scanf("%d", &T);
	while(T--)
	{
		int n;
		scanf("%d", &n);
		for(int i = 0; i < n; i++)
		{
			scanf("%d", &a[0][i]);
		}

		int j = 0;
		bool flag = false;
		for(int l = 0; l < 2000; l++)
		{
			bool zero = true;
			int k = j ? 0 : 1;
			for(int i = 0; i < n; i++)
			{
				int m = (i + 1) % n;
				a[k][i] = fabs(a[j][i] - a[j][m]);
				if(a[k][i] != 0)
					zero = false;
			}
			j = k;
			if(zero)
			{
				printf("ZERO\n");
				flag = true;
				break;
			}
		}
		if(!flag)
			printf("LOOP\n");
	}
	return 0;
}

习题5-3

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
	简单的队列操作
*/

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	int n;
	while(~scanf("%d", &n) && n)
	{
		bool first = true;
		queue<int> q;
		for(int i = 1; i <= n; i++)
			q.push(i);
		printf("Discarded cards:");
		while(1)
		{
			if(q.size() == 1)
			{
				printf("\nRemaining card: %d\n", q.front());
				break;
			}
			int x = q.front();
			if(first)
			{
				first = false;
				printf(" %d", x);
			}
			else
				printf(", %d", x);
			q.pop();
			x = q.front();
			q.pop();
			q.push(x);
		}
	}
	return 0;
}

习题5-4

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
	要读懂题意!!!
	题目意思是,申请a到b和b到a的数量一样就OK。
	用数组,每输入两个数就交换
	如果最后数组和原数组相同则OK
	a,b b,c c,a的情况也行
*/

const int maxn = 500000 + 10;
int arr[maxn];

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	int n;
	while(~scanf("%d", &n) && n)
	{
		for(int i = 0; i < n; i++)
			arr[i] = i;
		for(int i = 0; i < n; i++)
		{
			int a, b;
			scanf("%d%d", &a, &b);
			swap(arr[a], arr[b]);
		}
		bool flag = false;
		for(int i = 0; i < n; i++)
		{
			if(arr[i] != i)
			{
				flag = true;
				printf("NO\n");
				break;
			}
		}
		if(!flag)
			printf("YES\n");
	}
	return 0;
}

习题5-5

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
	枚举每一个单词
	如果再枚举两个单词是否能拼成它,会超时
	所以用substr把这个单词拆分
	用map映射,在里面的单词映射成1,不在的0
*/

const int maxn = 120000 + 10;
map<string, bool> m;
string s[maxn];

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	int n = 0;
	while(cin >> s[n])
	{
		m[s[n++]] = 1;
	}
	string a, b;
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < s[i].size() - 1; j++)
		{
			a = s[i].substr(0, j + 1);  
	        if(!m[a])
	        	continue;  
	        b = s[i].substr(j + 1);  
	        if(!m[b])
	        	continue;  
	        cout << s[i] << endl;  
	        break;  
		}
	}
	return 0;
}

习题5-6

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
	做了很长时间,题目要求考虑不周,代码能力,还忘记初始化
*/

struct node
{
	int x, y;
	bool flag;			//判断是否找到了对称点
	bool operator < (const node &b) const
	{
		if(x == b.x)
			return y < b.y;
		return x < b.x;
	}
}node[1010];

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	int T;
	scanf("%d", &T);
	while(T--)
	{
		int n;
		scanf("%d", &n);
		for(int i = 0; i < n; i++)
		{
			scanf("%d%d", &node[i].x, &node[i].y);
			node[i].x *= 2;			//为了避免出现小数,横坐标都乘2
			node[i].flag = false;	//初始化!!!
		}
		sort(node, node + n);
		int mid = (node[0].x + node[n - 1].x) / 2;
		bool ok = true;
		for(int i = 0; i < n; i++)
		{
			if(node[i].x == mid)	//在对称轴上
			{
				node[i].flag = true;
				continue;
			}
			if(node[i].flag)		//这点已经有对称点了
				continue;
			if(!ok)					//存在点没有对称轴
				break;
			int a = 2 * mid - node[i].x;
			for(int j = n - 1; j > 0; j--)
			{				
				if(i == j)			//同一点
					continue; 
				if(node[j].flag)	//这点已经有对称点了
					continue;
				if(node[j].x == a)
				{
					if(node[j].y == node[i].y)
					{
						node[j].flag = true;
						node[i].flag = true;
						break;
					}
					else
						continue;
				}
				else if(node[j].x < a)
				{
					ok = false;
					break;
				}
				else
					continue;
			}
		}
		bool yes = true;
		if(!ok)
		{
			printf("NO\n");
			yes = false;
		}
		else
		{
			for(int i = 0; i < n; i++)
			{
				if(!node[i].flag)
				{
					printf("NO\n");
					yes = false;
					break;
				}
			}
			if(yes)
				printf("YES\n");
		}
	}
	return 0;
}

习题5-7

方法一:直接用数组模拟一个队列

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
	模拟一个队列即可
*/

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	int T;
	scanf("%d", &T);
	while(T--)
	{
		int q[150];
		int front = 0, rear = 0;
		int n, m, ans = 0;
		scanf("%d%d", &n, &m);
		for(int i = 0; i < n; i++)
		{
			int x;
			scanf("%d", &x);
			q[rear++] = x;
		}
		while(1)
		{
			int x = q[front];
			bool flag = false;
			int i;
			for(i = (front + 1) % 150; i != rear; i = (i + 1) % 150)
			{
				if(q[i] > x)
				{
					flag = true;
					break;
				}
			}
			if(flag)
			{
				if(m == front)
					m = rear;
				front = (front + 1) % 150;
				q[rear] = x;
				rear = (rear + 1) % 150;
			}
			else
			{
				ans++;
				if(m == front)
				{
					printf("%d\n", ans);
					break;
				}
				front = (front + 1) % 150; 
			}
		}
	}
	return 0;
}

方法二:用优先队列

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<cstdlib>
#include<ctime>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int gcd(int a, int b){return b==0?a:gcd(b,a%b);}

/*
	可以用优先队列存权值
*/

struct node
{
	int p;		//权值		
	bool t;		//是否是要求的
};

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	int T;
	scanf("%d", &T);
	while(T--)
	{
		int n, m, ans = 0;
		queue<node> q;	
		priority_queue<int> pq;			
		//普通的优先队列,从大到小排列,也可用数组存
		
		scanf("%d%d", &n, &m);
		for(int i = 0; i < n; i++)
		{
			node x;
			scanf("%d", &x.p);
			if(i == m)
				x.t = true;
			else
				x.t = false;
			q.push(x);
			pq.push(x.p);
		}
		
		while(1)
		{
			node x = q.front();
			int j = pq.top();
			q.pop();
			if(x.p == j)
			{
				ans++;
				pq.pop();
				if(x.t)
				{
					printf("%d\n", ans);
					break;
				}
			}
			else
			{
				q.push(x);
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36720186/article/details/80052858
今日推荐