題目網址: 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個題目之後,後邊的題目就切不動了...
下次一定會更加優秀!