目录
hihocoder 编程练习赛75
题目1 : 工作城市分配
题意分析:
1.题是什么?
2.思路
ac代码
题目2 : 工作城市分配2
题意分析:
1.题是什么?
2.思路
ac代码
题目3 : 顺子组合
题目分析:
1.题是什么?
2.思路
ac代码
题目4 : 栈的加强版
题意分析:
1.题是什么?
2.思路
ac代码
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
H公司在北京和上海两个城市各有一间办公室。该公司最近新招募了2N名员工,小Hi负责把这2N名员工分配到北京和上海各N名。
于是小Hi调查了新员工对于北京和上海的意愿,我们用Bi和Si表示。Bi代表如果分配第i名员工去北京,他的满意指数;Si代表如果分配去上海,他的满意指数。
小Hi想知道如何分配才能使2N名员工的满意指数之和最高。
第一行包含一个整数N。
以下2N行每行包含两个整数Bi和Si。
1 ≤ N ≤ 1000
0 ≤ Bi, Si ≤ 100000
一个整数代表最高可能的满意指数之和。
样例输入
2
100 50
80 80
50 100
10 30
样例输出
310
其实就是给你2*n对数字,你要选出其中n对数字取其左数,n对数字取其右数,使得这2*n个数字之和最大化.
略一看有点博弈和背包dp的感觉,因为你选择了这对数的左数就代表你失去了它的右数,怎么去选择才能获取到最大和就是核心问题,而涉及到选择与最优结果自然第一时间该想到dp递推得最优结果.这道题就是dp.
dp[i][j]表示前面的人分配完之后北京分配i人上海分配j人时可达到的最高满意指数,而递推公式如代码
(另一个思路:贪心选取,以shanghai[i]-beijing[i]做升序排序,前一半去北京,后一半去上海,这个仅适用与A题)
#include
#include
using namespace std;
const int maxn=1001;
int beijing[2*maxn],shanghai[2*maxn];
int dp[maxn][maxn];//dp[i][j]表示前面的人分配完之后北京分配i人上海分配j人时可达到的最高满意指数
int main(){
int n;
cin>>n;
int ans=0;
for(int i=1;i<=2*n;i++) cin>>beijing[i]>>shanghai[i];
for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) dp[i][j]=0;
for(int i=1;i<=2*n;i++){ //分配第i个人
//如果给北京
for(int j=0;j<=i-1&&j
#include
#include
using namespace std;
const int maxn=1001;
typedef pair pa;
pa a[2*maxn];//first存的对北京的满意度bi,second存的对上海的满意度si
bool comp(const pa &a,const pa &b){
return a.second-a.first>n;
for(int i=1;i<=2*n;i++) cin>>a[i].first>>a[i].second;
sort(a+1,a+2*n+1,comp);
int ans=0;
for(int i=1;i<=n;i++) ans+=a[i].first; //前一半去北京
for(int i=n+1;i<=2*n;i++) ans+=a[i].second; //后一半去上海
cout<
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
H公司在北京、上海和纽约三个城市各有一间办公室。该公司最近新招募了3N名员工,小Hi负责把这3N名员工分配到北京、上海和纽约各N名。
于是小Hi调查了新员工对于北京、上海和纽约的意愿,我们用Bi、Si和Ni表示。Bi代表如果分配第i名员工去北京,他的满意指数;Si代表如果分配去上海的满意指数;Ni代表如果分配去纽约的满意指数。
小Hi想知道如何分配才能使3N名员工的满意指数之和最高。
第一行包含一个整数N。
以下3N行每行包含两个整数Bi、Si和Ni。
1 ≤ N ≤ 100
0 ≤ Bi, Si, Ni ≤ 100000
一个整数代表最高可能的满意指数之和。
样例输入
2
100 50 100
80 80 100
50 100 100
10 30 100
80 40 30
20 70 50
样例输出
550
和A题没什么区别,只是现在是把3*n个人分给3个地方
和A一样,dp
#include
#include
using namespace std;
const int maxn=101;
int beijing[3*maxn],shanghai[3*maxn],niuyue[3*maxn];
int dp[maxn][maxn][maxn];//dp[i][j][k]表示前面的人分配完之后北京分配i人上海分配j人纽约分配k人时可达到的最高满意指数
int main(){
int n;
cin>>n;
for(int i=1;i<=3*n;i++) cin>>beijing[i]>>shanghai[i]>>niuyue[i];
for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) for(int k=0;k<=n;k++) dp[i][j][k]=0;
for(int i=1;i<=3*n;i++){ //分配第i个人
//如果给北京
for(int j=0;j<=i-1&&j
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
你有一个包含N个整数的数组:A1, A2, ... AN。我们将3个或3个以上数值连续的整数序列称作顺子,例如[1, 2, 3]、[5, 6, 7, 8]和[10, 11, 12, 13, 14, 15, 16]都是顺子。
请你判断A数组是否能拆分成若干个顺子的组合。要求每个整数Ai恰好只属于其中一个顺子。
第一行包含一个整数T代表测试数据的组数。
每组数据第一行包含一个整数N。
每组数据第二行包含N个整数A1, A2, ... AN。
1 ≤ T ≤ 10
1 ≤ N ≤ 10000
0 ≤ Ai ≤ 100000
对于每组数据输出YES或者NO代表是否能拆分成顺子组合。
样例输入
2
7
4 1 3 2 5 4 6
8
4 1 3 2 5 4 6 6
样例输出
YES
NO
如果是四川人那应该玩过跑得快(也叫蒙鸡),其实题就是给你n个数字,三个或三个以上的相邻数字被认为是连子,如果每个数字都作且仅作为某个连子的一部分,则输出YES,否则NO.
首先发现数字只能在100000以内,故而我选择了使用计数排序那种思想接这n个数字,然后从0到100000挨个判断看是否每个数都是连子的一部分
length1表示当前位置前方紧接的长度为1的连子数目,length2表示长度为2的连子数目,length3表示长度为3及以上的连子数目
哪个地方要是有长度为1或2的连子断开了或者说到最后都还有为1或为2的连子存在,自然就NO
#include
using namespace std;
const int maxa=100001;
int a[maxa];
int main(){
int t;
cin>>t;
while(t--){
int n,temp;
cin>>n;
for(int i=0;i>temp;
a[temp]++;
}
bool ans=true;
int length1=0,length2=0,length3=0;//length1表示当前位置紧接的前方长度为1的连子数目,length2表示长度为2的连子数目,length3表示长度为3及以上的连子数目
int nu=10;
for(int i=0;i=length1+length2+length3){
int tlength1=length1,tlength2=length2,tlength3=length3;
length1=a[i]-(tlength1+tlength2+tlength3);
length2=tlength1;
length3=tlength3+tlength2;
}
else if(a[i]>=length1+length2){
length3=a[i]-(length1+length2)+length2;
length2=length1;
length1=0;
}
else{
ans=false;
break;
}
}
if(length1||length2) ans=false;
if(ans) cout<<"YES"<
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
请你实现一个加强版的栈,支持以下操作:
push x: 向栈顶加入一个整数x
pop: 从栈顶弹出一个整数,并且输出该整数
inc k x: 将处于栈底的前k个整数加x。
第一行包含一个整数N,代表操作的数量。
以下N行每行一条操作。
1 ≤ N ≤ 200000, 0 ≤ x ≤ 100000, 1 ≤ k ≤ 当前栈的大小
对于每一个pop操作,输出弹出的整数数值。
样例输入
6
push 1
inc 1 2
push 2
inc 2 2
pop
pop
样例输出
4
5
就是要写一个加强的栈,除了原有的push,pop功能之外还要有一个inc功能支持对栈底k个元素全加x
数组模拟栈这是自然的,然后由于操作数最大二十万,对于inc操作不可能真的对栈底部每个数作加x操作,故而我们只用把每次inc操作记录下来,在pop时再加上去,记得还要更新一下被影响到的inc操作.
#include
using namespace std;
typedef pair pa;
const int maxn=200000;
int a[maxn],top=-1;
int increasing[maxn];
void push(int t){
a[++top]=t;
}
int pop(){
if(top>0) increasing[top-1]+=increasing[top];//很重要,对inc的更新
int ans=a[top]+increasing[top];
increasing[top]=0; //很重要,对inc的更新
top--;
return ans;
}
void inc(int k,int x){
increasing[k-1]+=x;
}
int main(){
int n;
cin>>n;
for(int i=0;i>order;
if(order=="push"){
int t;
cin>>t;
push(t);
}
else if(order=="pop"){
cout<>t1>>t2;
inc(t1,t2);
}
}
return 0;
}