stl粗浅总结

最近把放假欠的stl的题目补完了,现在通过题目做一个总结。
放链接http://codeforces.com/problemset/problem/612/C
C. Replace To Make Regular Bracket Sequence
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given string s consists of opening and closing brackets of four kinds <>, {}, [], (). There are two types of brackets: opening and closing. You can replace any bracket by another of the same type. For example, you can replace < by the bracket {, but you can't replace it by ) or >.

The following definition of a regular bracket sequence is well-known, so you can be familiar with it.

Let's define a regular bracket sequence (RBS). Empty string is RBS. Let s1 and s2 be a RBS then the strings <s1>s2, {s1}s2, [s1]s2, (s1)s2 are also RBS.

For example the string "[[(){}]<>]" is RBS, but the strings "[)()" and "][()()" are not.

Determine the least number of replaces to make the string s RBS.

Input

The only line contains a non empty string s, consisting of only opening and closing brackets of four kinds. The length of s does not exceed 106.

Output

If it's impossible to get RBS from s print Impossible.

Otherwise print the least number of replaces needed to get RBS from s.

Examples
Input
Copy
[<}){}
Output
2
Input
Copy
{()}[]
Output
0
Input
Copy
]]
Output
Impossible

题目大意就是给出一串字符串左右括号需要两两匹配,只有同类型且一左一右才可以进行匹配,当类型不同时,可以进行一次变化使类型匹配如()、[]、{}、<>或者(string)此string已符合题目要求。如最后不能全部完成匹配则输出Impossible否则输出变化的次数。
是一道很裸的stack的题目,可笑我当年还不知道。自己极复杂的办法做的还不停想着怎么简化。
先贴上一开始很傻的代码(已ac)

#include<stdio.h>
#include<string.h>
char s[1000005];
char left[1000005];
int main()
{
	int i,r=0,l=0,ll=0,change=0;
	scanf("%s",s);
	for(i=0;i<strlen(s);i++)
	{
		if(ll<0) break;
		switch(s[i])
		{
			case '{':left[ll]='{';ll++;l++;break;
			case '[':left[ll]='[';ll++;l++;break;
			case '<':left[ll]='<';ll++;l++;break;
			case '(':left[ll]='(';ll++;l++;break;
			case '}':if(left[ll-1]!='{') change++;ll--;r++;break;
			case ']':if(left[ll-1]!='[') change++;ll--;r++;break;
			case ')':if(left[ll-1]!='(') change++;ll--;r++;break;
			case '>':if(left[ll-1]!='<') change++;ll--;r++;break;  
		}
	}
	if(r!=l||ll!=0) printf("Impossible");
	else printf("%d",change);
} 

开学后静下心来好好学习了stl以后,发现stack可以很方便解决这个问题。
注:stack为一种后进先出的数据结构,最后压入栈的元素将被最先调用。如同一个瓶子向内不断塞入纸片,每次只能取出最上面的纸。使用stack时需要添加头文件stack

思路:先判断栈是否为空,若为空,而此时为左括号则直接判定为错右括号则直接压入栈,若不为空,当为右括号时,直接压入栈中,若为左括号则与栈顶元素比较若为同类则无视发生,若为异类则令变化加一,完毕后将栈顶元素弹出。

这里用到几个set的简单的成员函数
先设置栈stack<char> q;

q.empty():用于检测栈是否为空,当栈为空时返回真
q.push(x):将x压入栈q中。

q.pop():将栈顶元素弹出栈
q.top():返回栈顶元素

下面贴代码:

#include<stdio.h>
#include<iostream>
#include<stack>
#include<string.h>
using namespace std;
char s[1000005];
int main()
{
	cin>>s;
	stack<char> q;
	int i,len,ok=1,change=0;
	len=strlen(s);
	for(i=0;i<len;++i)
	{
		if(!q.empty())
		{
			if(s[i]==')'||s[i]=='>'||s[i]=='}'||s[i]==']')
			{
				switch(q.top())
				{
					case '{':if(s[i]!='}') ++change;break;
					case '[':if(s[i]!=']') ++change;break;
					case '<':if(s[i]!='>') ++change;break;
					case '(':if(s[i]!=')') ++change;break;
				}
				q.pop();
			}
			else q.push(s[i]);
		}
		else
		{
			if(s[i]==')'||s[i]=='>'||s[i]=='}'||s[i]==']')
			ok=0;
			else
			{
				q.push(s[i]);
			}
		}
	}
	if(!q.empty()) ok=0;
	if(!ok) printf("Impossible\n");
	else cout<<change<<endl;
	

}

然后是第二题 CodeForces - 620C
放链接http://codeforces.com/problemset/problem/620/C
C. Pearls in a Row
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

There are n pearls in a row. Let's enumerate them with integers from 1 to n from the left to the right. The pearl number i has the type ai.

Let's call a sequence of consecutive pearls a segment. Let's call a segment good if it contains two pearls of the same type.

Split the row of the pearls to the maximal number of good segments. Note that each pearl should appear in exactly one segment of the partition.

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

Input

The first line contains integer n (1 ≤ n ≤ 3·105) — the number of pearls in a row.

The second line contains n integers ai (1 ≤ ai ≤ 109) – the type of the i-th pearl.

Output

On the first line print integer k — the maximal number of segments in a partition of the row.

Each of the next k lines should contain two integers lj, rj (1 ≤ lj ≤ rj ≤ n) — the number of the leftmost and the rightmost pearls in the j-th segment.

Note you should print the correct partition of the row of the pearls, so each pearl should be in exactly one segment and all segments should contain two pearls of the same type.

If there are several optimal solutions print any of them. You can print the segments in any order.

If there are no correct partitions of the row print the number "-1".

Examples
Input
Copy
5
1 2 3 4 1
Output
1
1 5
Input
Copy
5
1 2 3 4 5
Output
-1
Input
Copy
7
1 2 1 3 1 2 1
Output
2
1 3
4 7
题目大意:出现两个相同元素则记为一个segment,要求分割出尽可能多的segment。如果不存在segment则输出-1
思路:从前向后便利以出现两个相同的元素为止,保存两端位置,之后重开一段序列继续计数。

因为数据极大所以选用了set。当已存入序列中已有当前元素时,则保存位置并且清空集合,需要注意的是,第一段总开头于1,而最后一段总结束于n
使用set时需要在程序头文件中包含声明#include<set>。接下来介绍几个本题需要使用的set的成员函数

首先令set<int> s
s.count(x):在s集合中检索x元素的数量(因为set中元素不重复,所以实际上只有1,0两种答案,就是用来检索是否存在x元素)


s.clear():用于清空集合s

s.insert(x):将x元素插入s集合中
下面贴代码:

#include<stdio.h>
#include<string.h>
#include<set>
using namespace std;
int u;
int left[300005],right[300005],ll,rr;
set<int> s;
int main()
{
	
	int n,i;
	while(~scanf("%d",&n))
	{
		memset(left,0,sizeof(left));
        memset(right,0,sizeof(right));
		left[0]=1;ll=1;rr=0;
		for(i=0;i<n;i++)
		{ 
		   scanf("%d",&u);
		   if(s.count(u))
		   {
		   	right[rr]=i+1;
		   	left[ll]=i+2;
		   	rr++;ll++;
		   	s.clear();
		   } 
		   else
		   {
		   	s.insert(u);
		   }
		} 
		right[rr-1]=n;
		if(rr==0) printf("-1\n");
		else
		{
			printf("%d\n",rr);
			for(i=0;i<rr;i++)
			{
				printf("%d %d\n",left[i],right[i]);
			}
		}
	}
} 


接着是第三题 UVA - 10815
链接https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1756

10815 - Andy's First Dictionary

Time limit: 3.000 seconds
题目大意:检索出一个文段中的所有的单词,同一个单词在大小写发生变化的前后均视为同一单词,并最后按照字典序输出。

思路:每读取一个单词之后,将其完全转换为小写,保存入向量。全部读取完毕之后将向量通过sort排序,输出第一个单词与其中所有与后一个不同的单词。(一开始自己不会做,上网找的答案,好像set也可以做?而且省去了sort的功夫。有空可以试试,据说数据奇大不用vector不行,也不知道真的假的)
要使用vector需要在程序的头文件中包含#include<vector>的声明,接下来介绍几个本体需要使用的vector的成员函数
先令vector<string> q
q.push_back(x):将x元素压入向量的尾部(向量不能将元素压到首部)
q.begin(),q.end():返回向量的头部与尾部
值得一提的是,因为已经进行过重载,所以向量可以像数组一样用q[i]的形式返回在i位置的值
下面贴代码:


#include<stdio.h>
#include<vector>
#include<string.h>
#include<algorithm>
#include<cctype> 
#include<iostream>
using namespace std;
char c,s[10005];
vector<string> q;
int main()
{
	int i=0;
	while(~(c=getchar()))
	{
		if(isalpha(c))//判断是否为字母 
		{
			s[i++]=tolower(c);//将大写都转化为小写 
		}
		else if(i!=0)
		{
			s[i]='\0';
			q.push_back(s);
			i=0;
		}
	}
	sort(q.begin(),q.end());
	for(int u=0;u<q.size();u++)
	{
		if(u==0||q[u]!=q[u-1])
		cout<<q[u]<<endl;
	}
} 
//注意测试时输入ctrl+z终止输入 

第四题火车进站问题
hdu 1022 http://acm.hdu.edu.cn/showproblem.php?pid=1022

Train Problem I

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 42948    Accepted Submission(s): 16077
很裸的一道栈的题目,可惜那时候还没学栈,太懒了。。用的笨办法模拟的
#include<stdio.h>
#include<string.h>
int main()
{
	int num,i,q,p,op[20]={0},o,in[20],out[20],station[20];
	char iin[20],oout[20];
	while(~scanf("%d %s %s",&num,iin,oout))
	{
		memset(op,0,sizeof(op));
        memset(station,0,sizeof(station));
		for(i=0;i<num;i++)
		{
			in[i]=iin[i]-'0';
			out[i]=oout[i]-'0';
		}
		q=p=0;o=0;
		for(i=0;i<num;i++)
		{
			station[q]=in[i];q++;o++;
			while(station[q-1]==out[p])
			{
				
				q--;p++;op[o]=1;o++;
				
			}
		}
		if(p==num)
		{
			printf("Yes.\n");
			for(i=0;i<o;i++)
			{
				if(op[i]==0) printf("in\n");
				else printf("out\n");
			}
		}
		else printf("No.\n");
		printf("FINISH\n");
	}
} 

第五题 数据结构综合
UVA11995 
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3146

题意是对一些数据给出一系列的操作(插入、弹出)让你通过数据进出的顺序来判断数据结构,可能为栈,队列,或者优先队列,或是不止一种数据结构,或哪种都不是
思路很简单,就是简单地把插入的数据同时插入到栈,队列,优先队列中,在弹出时再比较数据结构被引用的数据和指令给出弹出的数据进行比较就可以了,如果不同则不是该种数据结构。
下面时代码:
#include<stdio.h>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;
int main()
{
	
	int n;
	int oper,element;
	int bo[3];
	while(~scanf("%d",&n))
	{
		int Size=0,can=0;
		fill(bo,bo+3,1);
		stack<int> s;
		queue<int> q;
		priority_queue<int> p;
		for(int i=0;i<n;i++)
		{
			scanf("%d %d",&oper,&element);
			if(oper==1&&can==0)
			{
				s.push(element);
				q.push(element);
				p.push(element);
				++Size;
			}
			else if(can==0)
			{
				if(Size==0) {fill(bo,bo+3,0);can=1;continue;}
				if(q.front()!=element) bo[1]=0;
				if(s.top()!=element) bo[0]=0;
				if(p.top()!=element) bo[2]=0;
				s.pop();p.pop();q.pop();--Size;
			}
		}
		int many=0;
		for(int i=0;i<3;i++)
		{
			
			if(bo[i]==1)many++;
		}
		if(many==0) printf("impossible\n");
		else if(many==1)
		{
			if(bo[0]==1) printf("stack\n");
			if(bo[1]==1) printf("queue\n");
			if(bo[2]==1) printf("priority queue\n");
		}
		else printf("not sure\n");
	}
} 

第六题 割玻璃(set容器与迭代器的使用)
CodeForces - 527C    http://codeforces.com/problemset/problem/527/C
C. Glass Carving
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Leonid wants to become a glass carver (the person who creates beautiful artworks by cutting the glass). He already has a rectangular w mm  ×  h mm sheet of glass, a diamond glass cutter and lots of enthusiasm. What he lacks is understanding of what to carve and how.

In order not to waste time, he decided to practice the technique of carving. To do this, he makes vertical and horizontal cuts through the entire sheet. This process results in making smaller rectangular fragments of glass. Leonid does not move the newly made glass fragments. In particular, a cut divides each fragment of glass that it goes through into smaller fragments.

After each cut Leonid tries to determine what area the largest of the currently available glass fragments has. Since there appear more and more fragments, this question takes him more and more time and distracts him from the fascinating process.

Leonid offers to divide the labor — he will cut glass, and you will calculate the area of the maximum fragment after each cut. Do you agree?

Input

The first line contains three integers w, h, n (2 ≤ w, h ≤ 200 000, 1 ≤ n ≤ 200 000).

Next n lines contain the descriptions of the cuts. Each description has the form H y or V x. In the first case Leonid makes the horizontal cut at the distance y millimeters (1 ≤ y ≤ h - 1) from the lower edge of the original sheet of glass. In the second case Leonid makes a vertical cut at distance x (1 ≤ x ≤ w - 1) millimeters from the left edge of the original sheet of glass. It is guaranteed that Leonid won't make two identical cuts.

Output

After each cut print on a single line the area of the maximum available glass fragment in mm2.

Examples
Input
Copy
4 3 4
H 2
V 2
V 3
V 1
Output
8
4
4
2
Input
Copy
7 6 5
H 4
V 3
V 5
H 2
V 1
Output
28
16
12
6
4
题意很简单就是不断给出割点进行割玻璃,然后求出面积最大的一块的面积。
思路上就是不断将新的点加入集合,然后让被割裂的线段的长度的线段-1并使新生成的两条线段的条数+1.
这里利用了set.find(x)这个函数去找出x元素在容器中的位置,通过迭代器来返回与之相邻的两个点,来对线段进行操作。
需要注意的是迭代器的定义格式如“set<int>::iterator o,p;”
代码如下:
#include<stdio.h>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
set<int> w;
set<int> h;
int wi[200005],hi[200005];//此长度的边的数量 
void cut(set<int> &q,int x,int *a)
{
	
	set<int>::iterator o,p;
	q.insert(x);o=p=q.find(x);
	o--;p++;--a[*p-*o];//去掉被破坏的边 
	++a[x-*o];++a[*p-x];//添加新边 
}
int main()
{
	int wl,hl,n;
	while(~scanf("%d%d%d",&wl,&hl,&n))
	{
		fill(wi,wi+200005,0);fill(hi,hi+200005,0);
		w.clear();h.clear();
		w.insert(0);w.insert(wl);
		h.insert(0);h.insert(hl);
		wi[wl]=1;hi[hl]=1;
		while(n--)
		{
			char s[10];int p;
			scanf("%s%d",s,&p);
			if(s[0]=='V') cut(w,p,wi);
			else cut(h,p,hi);
			while(!wi[wl]) --wl;
			while(!hi[hl]) --hl;
			printf("%lld\n",LL(wl)*LL(hl));
		}
	}
} 

第7题 输出非重复的单词
uva 156

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=92

题意是输出所有没有重复的单词(既忽略大小写因素后,构成的字母不同)。

思路很简单就是将所有的单词都转化为纯小写状态之后,再进行sort排序,并与其原型一同存入一个multiset中,通过count函数找出其字母是否重复,最后将不重复的单词的原型存入一个集合中,最后输出。

本题依旧要使用迭代器。

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<map>
#include<set>
#include<string>
#include<string.h>
using namespace std;
multimap<string,string> q;
set<string> p;


int main()
{
	char c,s[25],b[25];
	
	int i=0;
	while(cin>>s,s[0]!='#')
	{
		strcpy(b,s);
		int len=strlen(b);
		for(int i=0;i<len;i++)
		{
			if(isalpha(b[i])) b[i]=tolower(b[i]);
		}
		sort(b,b+len);
		q.insert(make_pair(b,s));
	}
	multimap<string,string>::iterator it;
	for(it=q.begin();it!=q.end();it++)
	{
		if(q.count(it->first)==1)
		p.insert(it->second);
	}
	set<string>::iterator pi;
	for(pi=p.begin();pi!=p.end();++pi)
	{
		cout<<*pi<<endl;
	}
	return 0;
} 

第八题 字符串对应
CodeForces - 501B http://codeforces.com/problemset/problem/501/B
B. Misha and Changing Handles
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Misha hacked the Codeforces site. Then he decided to let all the users change their handles. A user can now change his handle any number of times. But each new handle must not be equal to any handle that is already used or that was used at some point.

Misha has a list of handle change requests. After completing the requests he wants to understand the relation between the original and the new handles of the users. Help him to do that.

Input

The first line contains integer q (1 ≤ q ≤ 1000), the number of handle change requests.

Next q lines contain the descriptions of the requests, one per line.

Each query consists of two non-empty strings old and new, separated by a space. The strings consist of lowercase and uppercase Latin letters and digits. Strings old and new are distinct. The lengths of the strings do not exceed 20.

The requests are given chronologically. In other words, by the moment of a query there is a single person with handle old, and handle new is not used and has not been used by anyone.

Output

In the first line output the integer n — the number of users that changed their handles at least once.

In the next n lines print the mapping between the old and the new handles of the users. Each of them must contain two strings, old and new, separated by a space, meaning that before the user had handle old, and after all the requests are completed, his handle is new. You may output lines in any order.

Each user who changes the handle must occur exactly once in this description.

Examples
Input
Copy
5
Misha ILoveCodeforces
Vasya Petrov
Petrov VasyaPetrov123
ILoveCodeforces MikeMirzayanov
Petya Ivanov
Output
3
Petya Ivanov
Misha MikeMirzayanov
Vasya VasyaPetrov123
题意:给出两个单词含义为从a指向b,求所有关系的起点与终点。
思路,一开始以为是并查集,后来发现只要简单的相连就抹去就可以了,使用了erase函数。
以下代码:
 
#include<stdio.h>
#include<iostream>
#include<map>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
	char a[25],b[25];
	int n;
	map<string,string> q;
	while(cin>>n)
	{
		while(n--)
		{
			cin>>a>>b;
			if(q.count(a)!=0)
			{
				q[b]=q[a];
				q.erase(a);
			}
			else
			{
				q[b]=a;
			}
		}
		cout<<q.size()<<endl;
		map<string,string>::iterator it;
		for(it=q.begin();it!=q.end();it++)
		{
			cout<<it->second<<' '<<it->first<<endl;
		}
	}
}
值得一提的是map中通过“迭代器->first(second)”的方法表示原元素(映射对象)。

第九题 全排列
hdu1027 http://acm.hdu.edu.cn/showproblem.php?pid=1027

Ignatius and the Princess II

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 9619    Accepted Submission(s): 5629


Problem Description
Now our hero finds the door to the BEelzebub feng5166. He opens the door and finds feng5166 is about to kill our pretty Princess. But now the BEelzebub has to beat our hero first. feng5166 says, "I have three question for you, if you can work them out, I will release the Princess, or you will be my dinner, too." Ignatius says confidently, "OK, at last, I will save the Princess."

"Now I will show you the first problem." feng5166 says, "Given a sequence of number 1 to N, we define that 1,2,3...N-1,N is the smallest sequence among all the sequence which can be composed with number 1 to N(each number can be and should be use only once in this problem). So it's easy to see the second smallest sequence is 1,2,3...N,N-1. Now I will give you two numbers, N and M. You should tell me the Mth smallest sequence which is composed with number 1 to N. It's easy, isn't is? Hahahahaha......"
Can you help Ignatius to solve this problem?
 

Input
The input contains several test cases. Each test case consists of two numbers, N and M(1<=N<=1000, 1<=M<=10000). You may assume that there is always a sequence satisfied the BEelzebub's demand. The input is terminated by the end of file.
 

Output
For each test case, you only have to output the sequence satisfied the BEelzebub's demand. When output a sequence, you should print a space between two numbers, but do not output any spaces after the last number.
 

Sample Input
6 4 11 8
 

Sample Output
1 2 3 5 6 4 1 2 3 4 5 6 7 9 8 11 10
 

Author
Ignatius.L
很裸的一道全排列题目只要用到next_permutation(数组头,数组尾)就可以直接进行如题中的排序

#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
int main()
{
	int in[1050];
	int m,n;
	while(cin>>n>>m)
	{
		for(int i=0;i<n;i++)
		{
			in[i]=i+1;
		}
		for(int i=1;i<m;i++)
		{
			next_permutation(in,in+n);
		}
		for(int i=0;i<n-1;i++)
		{
			cout<<in[i]<<' ';
		}
		cout<<in[n-1]<<endl;
	}
}
    总结了一些在stl学习中遇到的题目,因为能力有限只是介绍了一些自己遇到的(主要是容器)的stl问题,希望对读到这篇博客的你有用


posted @ 2018-02-28 23:58  Fly_White  阅读(134)  评论(0编辑  收藏  举报