题目网址: http://njoj.org/Contest/80/
B题
水题,题目标程有错...注意边界条件。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define Maxn 100005
using namespace std;
int a[Maxn];
int main(){
int n,m;
while (~scanf("%d%d",&n,&m)){
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);
int ans=0;
for (int i=1;i<=n-1;i++){
if (a[i+1]-a[i]>=200){
ans+=(a[i+1]-a[i]-200)*2;
}
}
if ((2000-a[n])*2>200){
ans+=(2000-a[n])*2-200;
}
if (a[1]>200) ans+=a[1]-200;
ans+=a[1];
if (ans>m) printf("HeHe~\n");
else printf("HaHa~\n");
}
return 0;
}
D题
题目大意:给出一个1到n的排列,求有多少子序列 的中位数恰好是b。
分析:显然,左边比b大的数-左边比b小的数=右边比b小的数-右边比b大的数。
那,我们在左边找出 比b大的数-比b小的数=i 的总数有多少个。在同样求解右边的时候,便可以找到相应的答案累加。
#include <iostream>
#include <cstring>
#include <cstdio>
#define MAXN 201000
#define Maxn 100005
using namespace std;
int a[MAXN];
int r[MAXN];
int main(){
int cases,n,m,p,k;
scanf("%d",&cases);
while (cases--){
scanf("%d%d",&n,&m);
memset(r,0,sizeof(r));
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
if (a[i]==m) p=i;
}
k=Maxn;
r[Maxn]=1;
for (int i=p+1;i<=n;i++){
if (a[i]>m) k++;
else k--;
r[k]=r[k]+1;
}
k=Maxn;
int ans=r[Maxn];
for (int i=p-1;i>=1;i--){
if (a[i]>m) k++;
else k--;
ans=ans+r[Maxn+Maxn-k];
}
printf("%d\n",ans);
}
return 0;
}
E题
求解阶梯型的小巷 最多容下多少水。
分析:最多只有一个”小山峰“能露出山头。我们找到最高的山峰(阶梯)之后,设为 Maxk,从1到Maxk做一次,n到Maxk做一次。
我写的有点复杂,思路还是很简单的。
#include <iostream>
#include <cstring>
#include <cstdio>
#define Maxn 100010
#define LL long long
using namespace std;
int a[Maxn],len[Maxn];
int main(){
int n;
LL wide,length;
while (~scanf("%d%lld",&n,&wide)){
int Maxk=0;a[0]=0;
for (int i=1;i<=n;i++){
scanf("%lld",&a[i]);
if (a[i]>a[Maxk]) Maxk=i;
}
for (int i=1;i<=n;i++){
scanf("%lld",&len[i]);
}
LL ans=0;
int p=1;
while (a[p]<=a[p+1]) p++;
while (p<Maxk){
int q=p+1;
while (q<=Maxk&&a[q]<a[p]) q++;
if (q<=Maxk){
LL tmp=min(a[q],a[p]);
for (int j=p+1;j<=q-1;j++){
ans+=(tmp-a[j])*len[j];
}
}
else break;
p=q;
while (p<Maxk&&a[p]<=a[p+1]) p++;
}
p=n;
while (a[p]<=a[p-1]) p--;
while (p>Maxk){
int q=p-1;
while (q>=Maxk&&a[q]<a[p]) q--;
if (q>=Maxk){
LL tmp=min(a[q],a[p]);
for (int j=p-1;j>=q+1;j--){
ans+=(tmp-a[j])*len[j];
}
}
else break;
p=q;
while (p>Maxk&&a[p]<=a[p-1]) p--;
}
printf("%lld\n",ans*wide);
}
return 0;
}
F题
按照题目要求,我们可以划分为0到k个阶段,第i个阶段最多打 i 枪。
我们可以从后往前做,push第 i 阶段的所有元素进去,再pop 最大元素出来 即可。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define LL long long
#define Maxn 200050
using namespace std;
priority_queue<LL> big;
LL a[Maxn];
int main(){
int n,c,k;
while (~scanf("%d%d",&n,&c)){
for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
if (c==0) c=1;
k=n/c;
LL ans=0;
while (!big.empty()) big.pop();
for (int i=k;i>=1;i--){
for (int j=i*c;j<=min((i+1)*c-1,n);j++){
big.push(a[j]);
}
ans+=big.top();
big.pop();
}
printf("%lld\n",ans);
}
return 0;
}
J题
还是比较简单的树形DP,我们返回的答案是一个结构体~~~因为答案要求两个。
在树形DP的时候,可以直接求解深度。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define Maxn 100010
#define Maxm 200100
using namespace std;
struct Ans{
int num,cost;
};
struct Edge {
int to, next;
int len;
}edge[Maxm +10];
int en, head[Maxn];
bool vis[Maxn];
inline void add_edge(int u, int v, int len) {
edge[en].to = v, edge[en].len = len, edge[en].next = head[u], head[u] = en++;
}
Ans TreeDP(int t,int deep){
Ans ans;
vis[t]=true;
ans.num=0;ans.cost=0;
for (int p=head[t];p!=-1;p=edge[p].next){
int to=edge[p].to,len=edge[p].len;
if (!vis[to]){
Ans tmp=TreeDP(to,deep+1);
if (len==2){
if (tmp.num==0){
ans.num+=1;ans.cost+=deep+1;
}
else{
ans.num+=tmp.num;ans.cost+=tmp.cost;
}
}
else{
ans.num+=tmp.num;ans.cost+=tmp.cost;
}
}
}
return ans;
}
int main(){
int n,u,v,len;
while (~scanf("%d",&n)){
en=0;
memset(head,-1,sizeof(head));
for (int i=1;i<=n-1;i++){
scanf("%d%d%d",&u,&v,&len);
add_edge(u,v,len);
add_edge(v,u,len);
}
memset(vis,false,sizeof(vis));
Ans ans=TreeDP(1,0);
printf("%d %d\n",ans.num,ans.cost);
}
return 0;
}
H题
Angel Beat!
题目大意,我们要去宿舍里找天使,每个宿舍有个编号,从1到n,a宿舍能到b宿舍,当且仅当 a宿舍的编号中 插入一个数字之后能变成 b宿舍的编号。现在假设 a能到b,b能到c,如果我们查找了b宿舍,那么a,c宿舍都不能查找了。题目问:我们最多能查找多少宿舍。(1<=n<=100000)
分析:神题。
A题
题目看到一半没看懂就放弃了= =
题目大意:给出一个N*M的矩阵,我们最少用多少1*L(L为任意长度)的木板来覆盖所有的‘#’,木板之间不能重叠,且 不能覆盖草地。
4 4 #.#. .### ###. ..#.
题目给出做法:网络流。我暂时没太想明白,欢迎和我交流。
总结,4个小时做完5个题目之后,后边的题目就切不动了...
下次一定会更加优秀!