HPU算法协会公开课第一期:【基础算法1】(STL 自定义sort 前缀和差分)

传送门(:https://vjudge.net/contest/374040#overview)
STL简单入门

A - 前m大的数

还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小希只想让你把答案中最大的M个数告诉她就可以了。
给定一个包含N(N<=3000)个正整数的序列,每个数不超过5000,对它们两两相加得到的N*(N-1)/2个和,求出其中前M大的数(M<=1000)并按从大到小的顺序排列。
Input
输入可能包含多组数据,其中每组数据包括两行:
第一行两个数N和M,
第二行N个数,表示该序列。

Output
对于输入的每组数据,输出M个数,表示结果。输出应当按照从大到小的顺序排列。
Sample Input
4 4
1 2 3 4
4 5
5 3 6 4
Sample Output
7 6 5 5
11 10 9 9 8

将数列1中的数据两两相加得到一个新的数列2,输出数列2的前m项
注意输出格式

#include<bits/stdc++.h>
#define ull unsigned long long
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
int a[3010],s[5000005];
bool cmp(int a,int b){
	return a>b;
}
int main(){
	int n,m;
	while(cin>>n>>m){
		int cnt=1;
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=1;i<n;i++){
			for(int j=i+1;j<=n;j++){
				s[cnt++]=a[i]+a[j];
			}
		}	
		sort(s+1,s+cnt,cmp);
		for(int i=1;i<m;i++) cout<<s[i]<<" ";
		cout<<s[m]<<endl;
	}
	return 0;
}

B - 稳定排序

大家都知道,快速排序是不稳定的排序方法。
如果对于数组中出现的任意a[i],aj,其中a[i]==a[j],在进行排序以后a[i]一定出现在a[j]之前,则认为该排序是稳定的。

某高校招生办得到一份成绩列表,上面记录了考生名字和考生成绩。并且对其使用了某排序算法按成绩进行递减排序。现在请你判断一下该排序算法是否正确,如果正确的话,则判断该排序算法是否为稳定的。
Input
本题目包含多组输入,请处理到文件结束。
对于每组数据,第一行有一个正整数N(0<N<300),代表成绩列表中的考生数目。
接下来有N行,每一行有一个字符串代表考生名字(长度不超过50,仅包含’a’~‘z’),和一个整数代表考生分数(小于500)。其中名字和成绩用一个空格隔开。
再接下来又有N行,是上述列表经过某排序算法以后生成的一个序列。格式同上。
Output
对于每组数据,如果算法是正确并且稳定的,就在一行里面输出"Right"。如果算法是正确的但不是稳定的,就在一行里面输出"Not Stable",并且在下面输出正确稳定排序的列表,格式同输入。如果该算法是错误的,就在一行里面输出"Error",并且在下面输出正确稳定排序的列表,格式同输入。

注意,本题目不考虑该排序算法是错误的,但结果是正确的这样的意外情况。
Sample Input
3
aa 10
bb 10
cc 20
cc 20
bb 10
aa 10
3
aa 10
bb 10
cc 20
cc 20
aa 10
bb 10
3
aa 10
bb 10
cc 20
aa 10
bb 10
cc 20
Sample Output
Not Stable
cc 20
aa 10
bb 10
Right
Error
cc 20
aa 10
bb 10

用结构体储存学生的名字和分数,用stable_sort()函数将结构体进行稳定排序(带有stable的函数可保证相等元素的原本相对次序在排序后保持不变)
后与题目所给的数据进行比较,然后输出就行了。
(传送门(stable_sort()与sort()的用法区别):https://blog.csdn.net/earbao/article/details/54911878)

#include<bits/stdc++.h>
#define ull unsigned long long
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
struct student{
	string id;
	int score;
}a[310],b[310];
bool cmp(const student a, const student b){
	return a.score>b.score;
}
int main(){
	int n;
	while(cin>>n){
		for(int i=1;i<=n;i++) cin>>a[i].id>>a[i].score;
		for(int i=1;i<=n;i++) cin>>b[i].id>>b[i].score;
		stable_sort(a+1,a+n+1,cmp);//带有stable的函数可保证相等元素的原本相对次序在排序后保持不变
		int cnt1=0,cnt2=0;
		for(int i=1;i<=n;i++){
			if(a[i].id==b[i].id) cnt1++;
			if(a[i].score==b[i].score) cnt2++;
		}
		if(cnt1==n&&cnt2==n) cout<<"Right"<<endl;
		else if(cnt1!=n&&cnt2==n){
			cout<<"Not Stable"<<endl;
			for(int i=1;i<=n;i++) cout<<a[i].id<<" "<<a[i].score<<endl;
		} 
		else{
			cout<<"Error"<<endl;
			for(int i=1;i<=n;i++) cout<<a[i].id<<" "<<a[i].score<<endl;
		}
	}
	return 0;
}

C - 开门人和关门人

每天第一个到机房的人要把门打开,最后一个离开的人要把门关好。现有一堆杂乱的机房签
到、签离记录,请根据记录找出当天开门和关门的人。
Input
测试输入的第一行给出记录的总天数N ( > 0 )。下面列出了N天的记录。
每天的记录在第一行给出记录的条目数M ( > 0 ),下面是M行,每行的格式为

证件号码 签到时间 签离时间

其中时间按“小时:分钟:秒钟”(各占2位)给出,证件号码是长度不超过15的字符串。
Output
对每一天的记录输出1行,即当天开门和关门人的证件号码,中间用1空格分隔。
注意:在裁判的标准测试输入中,所有记录保证完整,每个人的签到时间在签离时间之前,
且没有多人同时签到或者签离的情况。
Sample Input
3
1
ME3021112225321 00:00:00 23:59:59
2
EE301218 08:05:35 20:56:35
MA301134 12:35:45 21:40:42
3
CS301111 15:30:28 17:00:10
SC3021234 08:00:00 11:25:25
CS301133 21:45:00 21:58:40
Sample Output
ME3021112225321 ME3021112225321
EE301218 MA301134
SC3021234 CS301133

这道题是给你一些数据,进机房的人的进入和离开时间,让你找出开门人(最早来的)和关门人(最晚走的),是想让你对时间进行排序。注意输入和输出都是字符串形式,我们可以用两个map来存进机房人的id和出的人id。因为我们是要对时间进行排序,所以键是时间,对应的值是id。这样map就自动排好序啦(map是根据字典序自动就对其中数据进行整理)。直接输出就行。

#include<bits/stdc++.h>
#define ull unsigned long long
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
map<string,string> mp1;
map<string,string> mp2;
int main(){
	int t;
	cin>>t;
	while(t--){
		mp1.clear();
		mp2.clear();
		int m;
		cin>>m;
		for(int i=1;i<=m;i++){
			string id,in,out;
			cin>>id>>in>>out;
			mp1[in]=id;
			mp2[out]=id;
		}
		map<string,string>::iterator it;
		it=mp1.begin();
		cout<<it->second<<" ";
		it=mp2.end();it--;
		cout<<it->second<<endl;
	}
	return 0;
}

D - EXCEL排序

Excel可以对一组纪录按任意指定列排序。现请你编写程序实现类似功能。
Input
测试输入包含若干测试用例。每个测试用例的第1行包含两个整数 N (<=100000) 和 C,其中 N 是纪录的条数,C 是指定排序的列号。以下有 N
行,每行包含一条学生纪录。每条学生纪录由学号(6位数字,同组测试中没有重复的学号)、姓名(不超过8位且不包含空格的字符串)、成绩(闭区间[0, 100]内的整数)组成,每个项目间用1个空格隔开。当读到 N=0 时,全部输入结束,相应的结果不要输出。
Output
对每个测试用例,首先输出1行“Case i:”,其中 i 是测试用例的编号(从1开始)。随后在 N 行中输出按要求排序后的结果,即:当 C=1 时,按学号递增排序;当 C=2时,按姓名的非递减字典序排序;当 C=3
时,按成绩的非递减排序。当若干学生具有相同姓名或者相同成绩时,则按他们的学号递增排序。
Sample Input
3 1
000007 James 85
000010 Amy 90
000001 Zoe 60
4 2
000007 James 85
000010 Amy 90
000001 Zoe 60
000002 James 98
4 3
000007 James 85
000010 Amy 90
000001 Zoe 60
000002 James 90
0 0
Sample Output
Case 1:
000001 Zoe 60
000007 James 85
000010 Amy 90
Case 2:
000010 Amy 90
000002 James 98
000007 James 85
000001 Zoe 60
Case 3:
000001 Zoe 60
000007 James 85
000002 James 90
000010 Amy 90

先用结构体数组存入学生数据,根据题目要求自定义排序方式(语文一定要好哇),输出就行。

#include<bits/stdc++.h>
#define ull unsigned long long
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
struct student{
	string id;
	string name;
	int score;
}stu[100010];
bool cmp1(const student a,const student b){
	return a.id<b.id;
}
bool cmp2(const student a,const student b){
	if(a.name==b.name) return a.id<b.id;
	else return a.name<b.name;
}
bool cmp3(const student a,const student b){
	if(a.score!=b.score) return a.score<b.score;
	else return a.id<b.id;
}
int main(){
	int n,c,k=1;
	while(cin>>n>>c&&n){
		for(int i=1;i<=n;i++) cin>>stu[i].id>>stu[i].name>>stu[i].score;
		printf("Case %d:\n",k);k++;
		if(c==1) sort(stu+1,stu+n+1,cmp1);	
		if(c==2) sort(stu+1,stu+n+1,cmp2);
		if(c==3) sort(stu+1,stu+n+1,cmp3);
		for(int i=1;i<=n;i++) cout<<stu[i].id<<" "<<stu[i].name<<" "<<stu[i].score<<endl;
	}
	return 0;
}

H - 表达式括号匹配

给出一个表达式,该表达式仅由字符(、)、+、-以及数字组成。

请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回"YES";否则返回"NO"。

输入格式
一行一个表达式,长度不超过
2000

输出格式
若匹配,则输出"YES";否则输出"NO"

Sample Input
2+(3-4)-2-6)
Sample Output
NO

经典题,栈的运用。‘( ’进来时直接存进栈,‘)’进来时判断栈为不为空,为空就存入,不为空再判断top是不是‘( ’,是的话弹出,不是就存入。运行到最后,看栈是不是空的,空的就说明此表达式合理嘛。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
stack<char> c;
string s;
int main(){
	cin>>s;
	int l=s.size();
	for(int i=0;i<l;i++){
		if(s[i]=='(') c.push(s[i]);
		if(s[i]==')'){
			if(!c.empty()){
				if(c.top()=='(') c.pop();
				else c.push(s[i]);
			}
			else c.push(s[i]);	
		}
	}
	if(c.empty()) cout<<"YES"<<endl;
	else cout<<"NO"<<endl;
	return 0;
}

I - 合并果子

现在有n堆果子,第i堆有ai个果子。现在要把这些果子合并成一堆,每次合并的代价是两堆果子的总果子数。求合并所有果子的最小代价。

Input
第一行包含一个整数T(T<=50),表示数据组数。
每组数据第一行包含一个整数n(2<=n<=1000),表示果子的堆数。
第二行包含n个正整数ai(ai<=100),表示每堆果子的果子数。

Output
每组数据仅一行,表示最小合并代价。

Sample Input
2
4
1 2 3 4
5
3 5 2 1 4
Sample Output
19
33

优先队列的使用。合并果子要代价最小的话,肯定每次都是两堆最小的果子进行合并。输入数据时,就直接用优先队列存。找出第一小,弹出,即找到第二小,又弹出。将合并后的果子堆再放回去,再找第一小,第二小,循环即可。
传送门:优先队列的使用:https://www.cnblogs.com/huashanqingzhu/p/11040390.html

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e7 + 5;
priority_queue< int,vector<int>,greater<int> > q;//优先队列 
int main(){
	int t;
	cin>>t;
	while(t--){
		while(q.size()) q.pop();
		int n;
		cin>>n;
		for(int i=0;i<n;i++){
			int a;
			cin>>a;
			q.push(a);
		} 
		ll res=0;
		while(q.size()>=2){
			int t1=q.top();
			q.pop();
			int t2=q.top();
			q.pop();
			res+=t1+t2;
			q.push(t1+t2); 
		}
		cout<<res<<endl;
	} 
	return 0;
}

J - Covered Points Count

You are given n segments on a coordinate line; each endpoint of every segment has integer coordinates. Some segments can degenerate to points. Segments can intersect with each other, be nested in each other or even coincide.

Your task is the following: for every k∈[1…n], calculate the number of points with integer coordinates such that the number of segments that cover these points equals k. A segment with endpoints li and ri covers point x if and only if li≤x≤ri.

Input
The first line of the input contains one integer n (1≤n≤2⋅105) — the number of segments.

The next n lines contain segments. The i-th line contains a pair of integers li,ri (0≤li≤ri≤1018) — the endpoints of the i-th segment.

Output
Print n space separated integers cnt1,cnt2,…,cntn, where cnti is equal to the number of points such that the number of segments that cover these points equals to i.

Examples
Input
3
0 3
1 3
3 8
Output
6 2 1
Input
3
1 3
2 4
5 7
Output
5 2 0
Note
The picture describing the first example:

Points with coordinates [0,4,5,6,7,8] are covered by one segment, points [1,2] are covered by two segments and point [3] is covered by three segments.

The picture describing the second example:

Points [1,4,5,6,7] are covered by one segment, points [2,3] are covered by two segments and there are no points covered by three segments.

差分+map
差分传送门:https://blog.csdn.net/Healer66/article/details/87201014

#include<bits/stdc++.h>
#define ull unsigned long long
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn = 2e5+5;
map<ll,ll> mp;
ll cnt[maxn];
int main(){
	ll n;
	cin>>n;
	for(ll i=1;i<=n;i++){
		ll l,r;
		cin>>l>>r;
		mp[l]++;
		mp[r+1]--;
	}
	ll last,ans=0;
	map<ll,ll>::iterator it;
	for(it=mp.begin();it!=mp.end();it++){
		if(it==mp.begin()){
			last=it->first;
			ans+=it->second;
			continue;
		}
		cnt[ans]+=it->first-last;
		last=it->first;
		ans+=it->second;
	}
	for(int i=1;i<=n;i++) cout<<cnt[i]<<(i==n ? "\n" : " ");
	return 0;
}

K - Ignatius and the Princess IV

“OK, you are not too bad, em… But you can never pass the next test.” feng5166 says.

“I will tell you an odd number N, and then N integers. There will be a special integer among them, you have to tell me which integer is the special one after I tell you all the integers.” feng5166 says.

“But what is the characteristic of the special integer?” Ignatius asks.

“The integer will appear at least (N+1)/2 times. If you can’t find the right integer, I will kill the Princess, and you will be my dinner, too. Hahahaha…” feng5166 says.

Can you find the special integer for Ignatius?
Input
The input contains several test cases. Each test case contains two lines. The first line consists of an odd integer N(1<=N<=999999) which indicate the number of the integers feng5166 will tell our hero. The second line contains the N integers. The input is terminated by the end of file.
Output
For each test case, you have to output only one line which contains the special number you have found.
Sample Input
5
1 3 2 3 3
11
1 1 1 1 1 5 5 5 5 5 5
7
1 1 1 1 1 1 1
Sample Output
3
5
1

水题。直接用map来存这个数和这个数出现的次数即可。

#include<bits/stdc++.h>
#define ull unsigned long long
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
map<int,int> mp;
int main(){
	int n;
	while(cin>>n){
		mp.clear();
		for(int i=1;i<=n;i++){
			int x;cin>>x;
			mp[x]++;
		}
		map<int,int>::iterator it;
		for(it=mp.begin();it!=mp.end();it++){
			int x=it->second;
			if(x>=((n+1)/2)){
				x=it->first;
				cout<<x<<endl;
				break;
			}
		}
	}
	return 0;
}

L - Stones

Because of the wrong status of the bicycle, Sempr begin to walk east to west every morning and walk back every evening. Walking may cause a little tired, so Sempr always play some games this time.
There are many stones on the road, when he meet a stone, he will throw it ahead as far as possible if it is the odd stone he meet, or leave it where it was if it is the even stone. Now give you some informations about the stones on the road, you are to tell me the distance from the start point to the farthest stone after Sempr walk by. Please pay attention that if two or more stones stay at the same position, you will meet the larger one(the one with the smallest Di, as described in the Input) first.
Input
In the first line, there is an Integer T(1<=T<=10), which means the test cases in the input file. Then followed by T test cases.
For each test case, I will give you an Integer N(0<N<=100,000) in the first line, which means the number of stones on the road. Then followed by N lines and there are two integers Pi(0<=Pi<=100,000) and Di(0<=Di<=1,000) in the line, which means the position of the i-th stone and how far Sempr can throw it.
Output
Just output one line for one test case, as described in the Description.
Sample Input
2
2
1 5
2 4
2
1 5
6 6
Sample Output
11
12

题意:给定n个石头的位置pi,和能够扔的距离Di,从左(0位置)往右走,碰到的石头为奇数个就往右扔,碰到的石头为偶数个就跳过,问最后一个石头距离出发点的距离
pair+优先队列的复杂使用,注意cmp的写法
传送门:BOOL OPERATOR() 几种变种实现的整理:https://www.cnblogs.com/wenlove/archive/2010/10/14/booloperator.html

#include<bits/stdc++.h>
#define ull unsigned long long
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
typedef pair<int,int> pa;//pair用来存一对元素 
struct cmp{//妙啊 
	bool operator()(pa a,pa b){
		if(a.first==b.first) return a.second>b.second;//距离从小到大排序
		else return a.first>b.first;//位置从小到大排序
	}
};
priority_queue <pa,vector<pa>,cmp >q;
int main(){
	int t;
	cin>>t;
	while(t--){
		while(!q.empty()) q.pop();
		int n;
		cin>>n;
		for(int i=1;i<=n;i++){
			int p,d;
			cin>>p>>d;
			q.push(pa(p,d));
		}
		int cnt=1;
		pa next;
		while(!q.empty()){
			next=q.top();
			q.pop();
			if(cnt&1) q.push(pa(next.first+next.second,next.second));
			cnt++;
		}
		cout<<next.first<<'\n'; 
	}
	return 0;
}

M - SnowWolf’s Wine Shop

After retired from hustacm, Sempr(Liangjing Wang) find a part-time-job in Snowwolf(Wei Xu)'s wine shop. There are different qualities of wine in the shop, and all of which has a rating describing the qualities. All the ratings are larger than 0 and smaller than 1,000,000. Everyday nearly Q people will go to his shop and buy a bottle of wine because of his kindness. Once a customer want an X qualified rating but there are no such one, Sempr will sell him a better one with the smallest rating. But the boss of the shop is Snowwolf, you know, so if no wine has no more than Y qualified ratings better than the customer’s request, Sempr will say sorry to them. Every morning, Xiangsanzi will send N bottles of different or same qualified wine.
Input
In the first line there is an Integer T(0<T<10), which means the number of test cases in the test file, then followed by T test cases.
For each test case;
In the first line, there are 3 Integers, N,Q and Y.
In the second line, there are N integers, which means the quality rating of each bottle of wines.
In the third line, there are Q integers, which means the requests of customers from dawn to dark.
Here, all the Integers are between 0 and 1,000,000
Output
For each test case, output “Case I:”, where I is the case number, then followed by Q different lines of integers, means the quality of wine Sempr will sell that time. If he could not sell any wine, just output -1.
Sample Input
2
2 3 3
2 3
1 2 3
2 3 0
2 3
3 1 2
Sample Output
Case 1:
2
3
-1
Case 2:
3
-1
2

multiset的使用(什么是multiset?就是一个不会去重但有序的集合)
这道题就是给你几瓶酒,几个人要喝酒,他们很牛逼,只喝大于自身酒量小于极限的酒。有一个函数,非常的方便:lower_bound(x),返回>=x的此中这个数的地址//注意注意!!这个函数返回的是指针的位置。
传送门:multiset用法总结:https://blog.csdn.net/sodacoco/article/details/84798621

#include<bits/stdc++.h>
#define ull unsigned long long
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
multiset<int> wine;
int main(){
	int t;
	cin>>t;
	for(int k=1;k<=t;k++){
		wine.clear();
		int n,q,y;
		cin>>n>>q>>y;
		for(int i=1;i<=n;i++){
			int x;cin>>x;
			wine.insert(x);
		}
		printf("Case %d:\n",k);
		for(int i=1;i<=q;i++){
			int x;cin>>x;
			multiset<int>::iterator it=wine.lower_bound(x);//注意注意!!这个函数返回的是指针的位置 
			if(it==wine.end()||*it-x>y) cout<<-1<<endl;
			else{
				cout<<*it<<endl;
				wine.erase(it);//把it所在位置的数删除 
			}
		}
	}
	return 0;
}

N - Alice, Bob and Candies

There are n candies in a row, they are numbered from left to right from 1 to n. The size of the i-th candy is ai.

Alice and Bob play an interesting and tasty game: they eat candy. Alice will eat candy from left to right, and Bob — from right to left. The game ends if all the candies are eaten.

The process consists of moves. During a move, the player eats one or more sweets from her/his side (Alice eats from the left, Bob — from the right).

Alice makes the first move. During the first move, she will eat 1 candy (its size is a1). Then, each successive move the players alternate — that is, Bob makes the second move, then Alice, then again Bob and so on.

On each move, a player counts the total size of candies eaten during the current move. Once this number becomes strictly greater than the total size of candies eaten by the other player on their previous move, the current player stops eating and the move ends. In other words, on a move, a player eats the smallest possible number of candies such that the sum of the sizes of candies eaten on this move is strictly greater than the sum of the sizes of candies that the other player ate on the previous move. If there are not enough candies to make a move this way, then the player eats up all the remaining candies and the game ends.

For example, if n=11 and a=[3,1,4,1,5,9,2,6,5,3,5], then:

move 1: Alice eats one candy of size 3 and the sequence of candies becomes [1,4,1,5,9,2,6,5,3,5].
move 2: Alice ate 3 on the previous move, which means Bob must eat 4 or more. Bob eats one candy of size 5 and the sequence of candies becomes [1,4,1,5,9,2,6,5,3].
move 3: Bob ate 5 on the previous move, which means Alice must eat 6 or more. Alice eats three candies with the total size of 1+4+1=6 and the sequence of candies becomes [5,9,2,6,5,3].
move 4: Alice ate 6 on the previous move, which means Bob must eat 7 or more. Bob eats two candies with the total size of 3+5=8 and the sequence of candies becomes [5,9,2,6].
move 5: Bob ate 8 on the previous move, which means Alice must eat 9 or more. Alice eats two candies with the total size of 5+9=14 and the sequence of candies becomes [2,6].
move 6 (the last): Alice ate 14 on the previous move, which means Bob must eat 15 or more. It is impossible, so Bob eats the two remaining candies and the game ends.
Print the number of moves in the game and two numbers:

a — the total size of all sweets eaten by Alice during the game;
b — the total size of all sweets eaten by Bob during the game.
Input
The first line contains an integer t (1≤t≤5000) — the number of test cases in the input. The following are descriptions of the t test cases.

Each test case consists of two lines. The first line contains an integer n (1≤n≤1000) — the number of candies. The second line contains a sequence of integers a1,a2,…,an (1≤ai≤1000) — the sizes of candies in the order they are arranged from left to right.

It is guaranteed that the sum of the values of n for all sets of input data in a test does not exceed 2⋅105.

Output
For each set of input data print three integers — the number of moves in the game and the required values a and b.

Example
Input
7
11
3 1 4 1 5 9 2 6 5 3 5
1
1000
3
1 1 1
13
1 2 3 4 5 6 7 8 9 10 11 12 13
2
2 1
6
1 1 1 1 1 1
7
1 1 1 1 1 1 1
Output
6 23 21
1 1000 0
2 1 2
6 45 46
2 2 1
3 4 2
4 4 3

模拟得我。。自己画图好理解写,英语也不行,语文也不行QAQ QAQ QAQ QAQ QAQ
在这里插入图片描述

#include<bits/stdc++.h>
#define ull unsigned long long
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
int c[1010];
int main(){
	int t;
	cin>>t;
	while(t--){
		int n;
		cin>>n;
		for(int i=1;i<=n;i++) cin>>c[i];
		int a=c[1],b=0,cnt1=1,cnt2=0,sum1=a,sum2=0;
		for(int l=1,r=n+1;l<r;){
			if(l+1==r) break;
			b=0;
			while(b<=a&&l<r-1){
				r--;	
				b+=c[r];
			}
			sum2+=b;
			cnt2++;
			if(l+1==r) break;
			a=0;	
			while(a<=b&&l<r-1){
				l++;
				a+=c[l];
			}
			sum1+=a;
			cnt1++;
		}
		cout<<cnt1+cnt2<<" "<<sum1<<" "<<sum2<<endl;
	} 
	return 0;
}

O - Special Elements

Pay attention to the non-standard memory limit in this problem.

In order to cut off efficient solutions from inefficient ones in this problem, the time limit is rather strict. Prefer to use compiled statically typed languages (e.g. C++). If you use Python, then submit solutions on PyPy. Try to write an efficient solution.

The array a=[a1,a2,…,an] (1≤ai≤n) is given. Its element ai is called special if there exists a pair of indices l and r (1≤l<r≤n) such that ai=al+al+1+…+ar. In other words, an element is called special if it can be represented as the sum of two or more consecutive elements of an array (no matter if they are special or not).

Print the number of special elements of the given array a.

For example, if n=9 and a=[3,1,4,1,5,9,2,6,5], then the answer is 5:

a3=4 is a special element, since a3=4=a1+a2=3+1;
a5=5 is a special element, since a5=5=a2+a3=1+4;
a6=9 is a special element, since a6=9=a1+a2+a3+a4=3+1+4+1;
a8=6 is a special element, since a8=6=a2+a3+a4=1+4+1;
a9=5 is a special element, since a9=5=a2+a3=1+4.
Please note that some of the elements of the array a may be equal — if several elements are equal and special, then all of them should be counted in the answer.

Input
The first line contains an integer t (1≤t≤1000) — the number of test cases in the input. Then t test cases follow.

Each test case is given in two lines. The first line contains an integer n (1≤n≤8000) — the length of the array a. The second line contains integers a1,a2,…,an (1≤ai≤n).

It is guaranteed that the sum of the values of n for all test cases in the input does not exceed 8000.

Output
Print t numbers — the number of special elements for each of the given arrays.

Example
Input
5
9
3 1 4 1 5 9 2 6 5
3
1 1 2
5
1 1 1 1 1
8
8 7 6 5 4 3 2 1
1
1
Output
5
1
0
4
0

这题就是说给你一个数列,让你看有多少个数可以由其他连续子数列的和得到。用前缀和求出所有连续子序列的和,判断就是了;

#include<bits/stdc++.h>
#define ull unsigned long long
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
int a[8010],b[8010],vis[8010];
int main(){
	int t;
	cin>>t;
	while(t--){
		memset(vis,0,sizeof(vis));
		int n,cnt=0;
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			b[i]=a[i]+b[i-1];
		}
		for(int i=1;i<n;i++){
			for(int j=i+1;j<=n;j++){
				int sum=b[j]-b[i-1];//前缀和求出所有子序列的和
				if(sum<=n) vis[sum]++;
			}
		}
		for(int i=1;i<=n;i++){
			if(vis[a[i]]) cnt++;
		}
		cout<<cnt<<'\n';
	} 
	return 0;
}

P - Max Sum

Given a sequence a[1],a[2],a[3]…a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.
Input
The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).
Output
For each test case, you should output two lines. The first line is “Case #:”, # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.
Sample Input
2
5 6 -1 5 4 -7
7 0 6 -1 1 -6 7 -5
Sample Output
Case 1:
14 1 4

Case 2:
7 1 6

一个dp,如果不输出区间左右的话,直接就是经典dp。这个dp[i]的意思就是一a[i]为结尾的最大连续区间的值,所以状态更新就是dp[i]=max(a[i],dp[i-1]+a[i])。 然而要输出,所以我们要保存最大连续区间的区间左右。也就是两种情况分别思考,画吧,画吧QAQ

#include<bits/stdc++.h>
#define ull unsigned long long
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
int a[100008],dp[100008];
int main(){
	int t;
	cin>>t;
	for(int k=1;k<=t;k++){
		int n,m=-maxn,l=1,r=1,ml,mr,temp=1;
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=1;i<=n;i++){
			if(a[i]>dp[i-1]+a[i]){
				dp[i]=a[i];
				l=i;r=i;
			}
			else{
				dp[i]=dp[i-1]+a[i];
				r=i;
			}
			if(dp[i]>m){
				m=dp[i];
				ml=l;
				mr=r;
			}
		} 
		printf("Case %d:\n%d %d %d\n",k,m,ml,mr);
        if(k!=t) cout<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值