SCAU 周训三

A - A HDU - 3183

1.题目描述:
Kiki likes traveling. One day she finds a magic lamp, unfortunately the genie in the lamp is not so kind. Kiki must answer a question, and then the genie will realize one of her dreams.
The question is: give you an integer, you are allowed to delete exactly m digits. The left digits will form a new integer. You should make it minimum.
You are not allowed to change the order of the digits. Now can you help Kiki to realize her dream?

Input
There are several test cases.
Each test case will contain an integer you are given (which may at most contains 1000 digits.) and the integer m (if the integer contains n digits, m will not bigger then n). The given integer will not contain leading zero.

Output
For each case, output the minimum result you can get in one line.
If the result contains leading zero, ignore it.

Sample Input
178543 4
1000001 1
100001 2
12345 2
54321 2

Sample Output
13
1
0
123
321

2.题意:
kiki喜欢旅游,某一天她游到了一个有羊神的地方,羊神可以实现她的愿望,前提是要满足一定的条件:给出n位数字,你可以删去m位,使得该组数字最小。(给出莫得前导0,结果必须删除前导0.)

3.思路:
一开始想着模拟,看了大佬的做法后有被秀到。等价变形的思想——删m个数字使之最大相当于取n-m个最大值,在哪个区间呢?第一个数是s[0]—>s[m](因为还要取n-m-1个),假设取到的坐标是i,则下一个应该在s[i+1]—>s[m+1]里取。实质上是贪心的题目。

4.代码:

//A
#include
#include
#include
#include
#include
#define FAST ios::sync_with_stdio(false)
using namespace std;
const int MAX_N=1000;
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	string s;
	int m;
	int ans[MAX_N];
	while(cin>>s>>m)
	{
		memset(ans,0,sizeof(ans));
		int tot=0;
		int index,l=0,r=m;
		m=s.size()-m;
		while(m--)
		{
			index=l;
			for(int j=l;j<=r&&j<(int)s.size();++j)
				if(s[index]>s[j])
					index=j;
			ans[tot++]=(s[index]-'0');
			l=index+1;
			r++;
		}
		int head=0;
		while(ans[head]==0&&head<tot) head++;
		if(head==tot) printf("0");
		for(;head<tot;++head) cout<<ans[head];
		cout<<endl;
	}
	return 0;
}

B - B CodeForces - 377A

1.题目描述:
Pavel loves grid mazes. A grid maze is an n × m rectangle maze where each cell is either empty, or is a wall. You can go from one cell to another only if both cells are empty and have a common side.
Pavel drew a grid maze with all empty cells forming a connected area. That is, you can go from any empty cell to any other one. Pavel doesn’t like it when his maze has too little walls. He wants to turn exactly k empty cells into walls so that all the remaining cells still formed a connected area. Help him.

Input
The first line contains three integers n, m, k (1 ≤ n, m ≤ 500, 0 ≤ k < s), where n and m are the maze’s height and width, correspondingly, k is the number of walls Pavel wants to add and letter s represents the number of empty cells in the original maze.
Each of the next n lines contains m characters. They describe the original maze. If a character on a line equals “.”, then the corresponding cell is empty and if the character equals “#”, then the cell is a wall.

Output
Print n lines containing m characters each: the new maze that fits Pavel’s requirements. Mark the empty cells that you transformed into walls as “X”, the other cells must be left without changes (that is, “.” and “#”).
It is guaranteed that a solution exists. If there are multiple solutions you can output any of them.

Examples
Input
3 4 2
#…#
…#.
#…

Output
#.X#
X.#.
#…

Input
5 4 5
#…
#.#.
.#…
…#
.#.#

Output
#XXX
#X#.
X#…
…#
.#.#

2.题意:
原本路径是连通图,减少任意k个‘.’,使之依旧为连通图。

3.思路:
大佬说看数据量,直接暴搜(暴力深度搜索)。因为原本连通图,走过地方标记,剩下的地方就没得作用直接打‘X’。

4.代码:

//B
#include
#include
#include
#include
#include
#define FAST ios::sync_with_stdio(false)
using namespace std;
const int MAX_N=1000+5;
bool path[MAX_N][MAX_N];
int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
int n,m,k,cnt,cnt_cur=1;
string s[MAX_N];
void dfs(int x,int y)
{
	
	if(cnt_cur==cnt-k)
	{
		path[x][y]=1;
		return;
	}
	path[x][y]=1;
	for(int i=0;i<4;++i)
	{
		if(cnt_cur==cnt-k) return;
		int tmpx=x,tmpy=y;
		int x=x+dir[i][0];
		int y=y+dir[i][1];
		if(!(x>=n||y>=m||x<0||y<0||path[x][y]||s[x][y]=='#'))
		{
			cnt_cur++;
			dfs(x,y);
		}
		x=tmpx;
		y=tmpy;
	}
}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	cin>>n>>m>>k;
	for(int i=0;i<n;++i)
		cin>>s[i];
	int obx,oby;
	for(int i=0;i<n;++i)
		for(int j=0;j<m;++j)
			if(s[i][j]=='.')
			{
				obx=i;
				oby=j;
				cnt++;
			}
	dfs(obx,oby);
	for(int i=0;i<n;++i)
		for(int j=0;j<m;++j)
			if(s[i][j]=='.'&&!path[i][j])
				s[i][j]='X';
	for(int i=0;i<n;++i) cout<<s[i]<<endl;
	return 0;
}

C - C CodeForces - 582A

1.题目描述:
The GCD table G of size n × n for an array of positive integers a of length n is defined by formula
Let us remind you that the greatest common divisor (GCD) of two positive integers x and y is the greatest integer that is divisor of both x and y, it is denoted as . For example, for array a = {4, 3, 6, 2} of length 4 the GCD table will look as follows:

SCAU 周训三_第1张图片
Given all the numbers of the GCD table G, restore array a.
Input

The first line contains number n (1 ≤ n ≤ 500) — the length of array a. The second line contains n2 space-separated numbers — the elements of the GCD table of G for array a.

All the numbers in the table are positive integers, not exceeding 109. Note that the elements are given in an arbitrary order. It is guaranteed that the set of the input data corresponds to some array a.

Output
In the single line print n positive integers — the elements of array a. If there are multiple possible solutions, you are allowed to print any of them.

Examples
Input
4
2 1 2 3 4 3 2 6 1 1 2 2 1 2 3 2

Output
4 3 6 2

Input
1
42

Output
42

Input
2
1 1 1 1

Output
1 1

2.题意:
给出一个集合(多重集,元素可重复)a,定义集合上的最大公约数矩阵:gij=gcd(i,j);现在给出矩阵中的所有数组成的数列(无序),还原出a。

3.思路:
当时想的思路很简单,出现过的记录下来,减去重复的剩下单数个,后来发现集合可以是多重集,就没办法了。这题本质上是贪心,我们已知:gcd(a,b)<=a<=b(假设a<=b),例如gcd(3,4)=1;gcd(3,12)=3;有了这个性质,我们可以每次拿走数列中最大的数,因为它必然是a中的一个元素;然后在计数处减去一个对应数字的数量,然后与之前得到的数字求gcd,因为gcd不计顺序,得到的数字对应的数量减二最后我们得到的数组就是集合a

4.代码:

//C
#include
#include
#include
using namespace std;
const int MAX_N=505;
int num[MAX_N*MAX_N];
int ans[MAX_N*MAX_N];
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	int n;scanf("%d",&n);
	map<int,int> m;
	int cnt=0;
	int cnt2=0;
	for(int i=0;i<n*n;++i)
	{
		scanf("%d",&num[i]);
		if(!m.count(num[i])) m[num[i]]=1,cnt++;
		else m[num[i]]++;
	}
	sort(num,num+n*n);
	for(int i=n*n-1;i>=0;--i)
	{
		if(m[num[i]]<=0) continue;
		else
		{
			ans[cnt2++]=num[i];
			m[num[i]]--;
			for(int j=0;j<cnt2;++j)
			{
				int k=gcd(ans[j],num[i]);
				m[k]-=2;
			}
		}
	}
	for(int i=0;i<cnt2;++i) printf("%d ",ans[i]);
	return 0;
}

D - D POJ - 2559

1.题目描述:
A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3, measured in units where 1 is the width of the rectangles:

SCAU 周训三_第2张图片
Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.

Input
The input contains several test cases. Each test case describes a histogram and starts with an integer n, denoting the number of rectangles it is composed of. You may assume that 1<=n<=100000. Then follow n integers h1,…,hn, where 0<=hi<=1000000000. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is 1. A zero follows the input for the last test case.

Output
For each test case output on a single line the area of the largest rectangle in the specified histogram. Remember that this rectangle must be aligned at the common base line.

Sample Input
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0

Sample Output
8
4000

Hint
Huge input, scanf is recommended.

2.题意:
求最大矩形面积,底是1。

3.思路:
单调栈的经典例题。我们用一个单调栈来维护左边能达到的最大值,以及右边能到的最大值,然后用一个数学技巧就是:2-1=1,但是1到2有两个数,所以我们在左边加多一个,右边的边界加一个就可以了。

4.代码:

//D
#include
#include
#include
#include
#include
#include
#define FAST ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
const int MAX_N=100000+5;
ll l[MAX_N],r[MAX_N],a[MAX_N];
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	ll n;
	while(scanf("%lld",&n)&&n)
	{
		stack<int> st;
		ll maxAera=0;
		for(int i=0;i<n;++i)
		{
			scanf("%lld",&a[i]);
			l[i]=r[i]=0;
		}
		for(int i=0;i<n;++i)
		{
			while(!st.empty()&&a[st.top()]>=a[i]) st.pop();
			l[i]= st.empty()?0:st.top()+1;
			st.push(i);
		}
		while(!st.empty()) st.pop();
		for(int i=n-1;i>=0;--i)
		{
			while(!st.empty()&&a[st.top()]>=a[i]) st.pop();
			r[i]= st.empty()?n:st.top();
			st.push(i);
		}
		for(int i=0;i<n;++i)
			maxAera=max(maxAera,a[i]*(r[i]-l[i]));
		printf("%lld\n",maxAera);
	}
	return 0;
}

E - E HDU - 3788

1.题目描述:
对给定的字符串(只包含’z’,‘o’,'j’三种字符),判断他是否能AC。
是否AC的规则如下:

  1. zoj能AC;
  2. 若字符串形式为xzojx,则也能AC,其中x可以是N个’o’ 或者为空;
  3. 若azbjc 能AC,则azbojac也能AC,其中a,b,c为N个’o’或者为空;

Input
输入包含多组测试用例,每行有一个只包含’z’,‘o’,'j’三种字符的字符串,字符串长度小于等于1000;

Output
对于给定的字符串,如果能AC则请输出字符串“Accepted”,否则请输出“Wrong Answer”。

Sample Input
zoj
ozojo
ozoojoo
oozoojoooo
zooj
ozojo
oooozojo
zojoooo

Sample Output
Accepted
Accepted
Accepted
Accepted
Accepted
Accepted
Wrong Answer
Wrong Answer

2.题意:

3.思路:
这题题面过于奇怪,其实说的是 z 前面的 o 乘以 z 与 j 之间的 o 要等于 j 后面的o。即 a*b==c。

4.代码:

//E
#include
#include
#include
#include
#include
#define FAST ios::sync_with_stdio(false)
using namespace std;
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	string s;
	while(cin>>s)
	{
		int i,N1=0,N2=0,N3=0;
		bool flag=0;
		for(i=0;s[i]!='j';++i)
			if(s[i]=='z') N1=i;
		N3=s.size()-i-1;
		N2=i-N1-1;
		if(N3==N1*N2&&N2)
			flag=true;
		if(!flag) cout<<"Wrong Answer"<<endl;
		else cout<<"Accepted"<<endl;
	}
	return 0;
}

F - F HDU - 1873

1.题目描述:
看病要排队这个是地球人都知道的常识。
不过经过细心的0068的观察,他发现了医院里排队还是有讲究的。0068所去的医院有三个医生(汗,这么少)同时看病。而看病的人病情有轻重,所以不能根据简单的先来先服务的原则。所以医院对每种病情规定了10种不同的优先级。级别为10的优先权最高,级别为1的优先权最低。医生在看病时,则会在他的队伍里面选择一个优先权最高的人进行诊治。如果遇到两个优先权一样的病人的话,则选择最早来排队的病人。
现在就请你帮助医院模拟这个看病过程。

Input
输入数据包含多组测试,请处理到文件结束。
每组数据第一行有一个正整数N(0 接下来有N行分别表示发生的事件。
一共有两种事件:
1:“IN A B”,表示有一个拥有优先级B的病人要求医生A诊治。(0 2:“OUT A”,表示医生A进行了一次诊治,诊治完毕后,病人出院。(0

Output
对于每个"OUT A"事件,请在一行里面输出被诊治人的编号ID。如果该事件时无病人需要诊治,则输出"EMPTY"。
诊治人的编号ID的定义为:在一组测试中,"IN A B"事件发生第K次时,进来的病人ID即为K。从1开始编号。

Sample Input
7
IN 1 1
IN 1 2
OUT 1
OUT 2
IN 2 1
OUT 2
OUT 1
2
IN 1 1
OUT 1

Sample Output
2
EMPTY
3
1
1

2.题意:

3.思路:
一个优先队列组,没什么难的。

4.代码:

//F
#include
#include
#include
#include
#include
#include
#define FAST ios::sync_with_stdio(false)
using namespace std;
struct node
{
	int num,w;
	bool operator<(const node& x)const
	{	if(w!=x.w)
			return w<x.w;
		else
			return num>x.num;
	}
}tmp;
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	long long Case;
	while(~scanf("%lld",&Case))
	{
		int I=0,a,b;
		string flag;
		priority_queue<node> q[4];
		while(Case--)
		{
			cin>>flag;
			if(flag=="IN")
			{
				cin>>a>>b;
				tmp.num=++I;
				tmp.w=b;
				q[a].push(tmp);
			}
			else
			{
				cin>>a;
				if(!q[a].empty())
				{
					cout<<q[a].top().num<<endl;
					q[a].pop();
				}
				else
					cout<<"EMPTY"<<endl;
			}
		}
	}
	return 0;
}

G - G CodeForces - 632B

1.题目描述:
Alice and Bob are playing a game. The game involves splitting up game pieces into two teams. There are n pieces, and the i-th piece has a strength pi.
The way to split up game pieces is split into several steps:
First, Alice will split the pieces into two different groups A and B. This can be seen as writing the assignment of teams of a piece in an n character string, where each character is A or B.
Bob will then choose an arbitrary prefix or suffix of the string, and flip each character in that suffix (i.e. change A to B and B to A). He can do this step at most once.
Alice will get all the pieces marked A and Bob will get all the pieces marked B.
The strength of a player is then the sum of strengths of the pieces in the group.
Given Alice’s initial split into two teams, help Bob determine an optimal strategy. Return the maximum strength he can achieve.

Input
The first line contains integer n (1 ≤ n ≤ 5·105) — the number of game pieces.
The second line contains n integers pi (1 ≤ pi ≤ 109) — the strength of the i-th piece.
The third line contains n characters A or B — the assignment of teams after the first step (after Alice’s step).

Output
Print the only integer a — the maximum strength Bob can achieve.

Examples
Input
5
1 2 3 4 5
ABABA

Output
11

Input
5
1 2 3 4 5
AAAAA

Output
15

Input
1
1
B

Output
1

Note
In the first sample Bob should flip the suffix of length one.
In the second sample Bob should flip the prefix or the suffix (here it is the same) of length 5.
In the third sample Bob should do nothing.

2.题意:
爱丽丝和鲍勃玩游戏,爱丽丝会将数组分为A、B两组,鲍勃可以选择一个数,将它前面或者后面的组别翻转(A->B;B->A)。然后爱丽丝拿走A,鲍勃拿走B。求鲍勃能的到的B组和最大是多少?

3.思路:
本质上是考前缀和后缀和问题,可以朴素的想:(1)翻前缀:A的前缀和+B的后缀和;(2)翻后缀:A的后缀和+B的前缀和。分别求就可以了。但是我们换一下:B的后缀等于:B的和-B的前缀;B的前缀等于:B的和-B的后缀。那么我们可以将上面简化为:**(1)翻前缀:A的前缀和-B的前缀和+B的和;(2)翻后缀:A的后缀-B的后缀+B的和。**这样代码我们可以十分简化,先预处理B的和。然后直接往后找/往前找(各一次)遇到A就加,遇到B就减;逐个比较取最大值。

4.代码:

//G
#include
#include
using namespace std;
typedef long long ll;
const int MAX_N=5*100005;
ll p[MAX_N],B=0;
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	int n;cin>>n;
	for(int i=0;i<n;++i) scanf("%lld",&p[i]);
	string s;cin>>s;
	for(int i=0;i<n;++i)
		if(s[i]=='B') B+=p[i];
	ll a=B,ans=B;
	for(int i=0;i<n;++i)
	{
		if(s[i]=='A') a+=p[i];
		else a-=p[i];
		if(ans<a) ans=a; 
	}
	a=B;
	for(int i=n-1;i>=0;--i)
	{
		if(s[i]=='A') a+=p[i];
		else a-=p[i];
		if(ans<a) ans=a; 
	}
	cout<<ans<<endl;
	return 0;
}

H - H CodeForces - 611B

1.题目描述:
The year 2015 is almost over.
Limak is a little polar bear. He has recently learnt about the binary system. He noticed that the passing year has exactly one zero in its representation in the binary system — 201510 = 111110111112. Note that he doesn’t care about the number of zeros in the decimal representation.
Limak chose some interval of years. He is going to count all years from this interval that have exactly one zero in the binary representation. Can you do it faster?
Assume that all positive integers are always written without leading zeros.

Input
The only line of the input contains two integers a and b (1 ≤ a ≤ b ≤ 1018) — the first year and the last year in Limak’s interval respectively.

Output
Print one integer – the number of years Limak will count in his chosen interval.

Examples
Input
5 10

Output
2

Input
2015 2015

Output
1

Input
100 105

Output
0

Input
72057594000000000 72057595000000000

Output
26

Note
In the first sample Limak’s interval contains numbers 510 = 1012, 610 = 1102, 710 = 1112, 810 = 10002, 910 = 10012 and 1010 = 10102. Two of them (1012 and 1102) have the described property.

2.题意:
要求区间[a,b]上二进制数只有一个0的数量。

3.思路:
这个是计数问题,当时TLE暴力试每一个。搜题解发现是规律题。我把我能理解的部分都分享出来吧,若有错误,请评论大佬指正!!
法一: dfs搜索法,暴力从1开始构造 我们知道,1不满足,12=2,满足,然后就可以在后面添1,就是i2+1。如果遇到不满足的i乘2就满足(这个我不知道为什么,我猜测是我们在构造的时候,将最后一个为零的地方漏掉了,那么乘二就可以补上这样的情况。)
法二:找规律:列出100以内的数:2 5 6 11 13 14 23 27 29 30 47 55 59 61 62 95;
分析一下相邻两项的差:(3,1)(5,2,1)(9,4,2,1)
我们可以发现,第一项是2的幂再加一,后面就是前一项除二取整。

4.代码:
法一:

//H
#include
#include
#include
#include
#include
#define FAST ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ll;
ll cnt,a,b;
void solve(ll x,bool flag)
{
	if(x>b) return;
	if(a<=x&&x<=b&&flag) cnt++;
	if(!flag)
		solve(x<<1,1);
	solve(x<<1|1,flag);
}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	cin>>a>>b;
	solve(1,0);
	cout<<cnt<<endl;
	return 0;
}

法二:

//H
#include
#include
#include
#include
#include
#define FAST ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ll;
ll cnt;
int main()
{
	ll p=0,tmp=2,j=1,x,y;
	cin>>x>>y;
	while(true)
	{
		if(!p)
		{
			j<<=1;
			p=j+1;
		}
		if(tmp<x);
		else if(tmp>y) break;
		else cnt++;
		tmp+=p;
		p>>=1;
	}
	cout<<cnt<<endl;
	return 0;
}

//我会补完的QAQ.

你可能感兴趣的:(SCAU周训)