题目名称

存款

旅行安排

花篮

夜晚

可执行文件名

Save

Plan

Baskets

Night

输入文件名

Save.in

Plan.in

Baskets.in

Night.in

输出文件名

Save.out

Plan.out

Baskets.out

Night.out

每个测试点时限

1s

1s

1s

1s

内存限制

64M

64M

64M

64M

测试点数目

10

10

10

10

每个测试点分值

10

10

10

10

题目类型

传统型

传统型

传统型

传统型

1、 文件名(程序名和输入输出文件名)对大小写无区分(Windows平台测试)。

2、 C/C++中函数main() 的返回值类型必须是int,程序正常结束时的返回值必须是0。

3、 统一评测平台为win7,内存2GB

4、 比赛期间请独立思考,完成问题

5、 比赛时间为3个小时,请选手把握好时间,认真检查,考出自己满意的成绩

Loongint的存款

【Description】

Loongint希望你能帮他规划一下今年一年的收入和支出。对于每一个月,Loongint可以选择打工挣钱或者陪MM去消费,每个月挣的钱(s)和消费的钱(d)的数额都是一定的。可是,Loongint的MM不希望Loongint有结余,因为这样Loongint可能去找别的MM。可是作为一个顶天立地的男人J,Loongint非常渴望能结余。

MM只能查Loongint任意连续五个月的经济情况,所以Loongint必须让任意连续五个月的收入都是负的(也就是五个月的总支出大于总收入)。求年终Loongint能结余么?如果能,输出最大结余,如果不能,输出No Save。

【Input】

第一行n表示有n组测试数据。

接下来n行,每行有s和d。

【Output】

n行,每行输出一年的最大结余或者No Save

【Sample Input】

2

1 1

14 6

【Sample Output】

0

No Save

【Hint】

对于30%的数据,1=<n<=100

对于100%的数据,1<=n<=100000;s,d和最后的解都属于Longint。

#include <iostream>
#include <cstdio>
#include <algorithm> 
using namespace std;
int n;
int s,d;
int solve(int s, int d){
    if (4*s-d<0) return 10*s-2*d;
    if (3*s-2*d<0) return 8*s-4*d;
    if (2*s-3*d<0) return 6*s-6*d;
    if (s-4*d<0) return 3*s-9*d;
    return -1;
}
int main(){
    freopen("save.in","r",stdin);
    freopen("save.out","w",stdout);
    scanf("%d\n",&n);
    for (int i=1;i<=n;i++){
        scanf("%d%d",&s,&d);
        int t=solve(s,d);
        if (t<0) printf("No Save\n");
        else printf("%d\n",t);
    }
    return 0;
}

 

Loongint的旅行安排

【Description】

Loongint和MM要出去旅行,出行前规划旅行方案时,MM给Loongint出了一个难题。她说,在她心中,不同的地方能给她不同的感受,而感受可以用喜爱值Li表示出来,她希望这次旅行能正好得到W的喜爱值。为了考验Loongint是否爱他,她只是给了Loongint所有的Li和W值,却并不告诉Loongint哪个是哪个…Loongint手头比较紧,只能支付去三个地方的费用,所以Loongint必须从这些数中找出三个Li和一个W,并且使W尽量的大。

Loongint一心想和MM去旅行,哪里有时间想这个问题,所以,交给了Hzoi同仁的你…

【Input】

输入数据有两组(为了防止No Solution骗分J)。

对于每一组,第一行n表示有n个数值,接下来n行为每个数值的大小。

【Output】

两组输出。分别为每组的答案。如果可以找出三个Li和一个W,那么就输出最大的W,如果不能,就输出No Solution。

【Sample Input】

4

5

5

5

5

4

1

2

3

6

【Sample Output】

No Solution

6

【Hint】

对于30%的数据,1=<n<=100

对于100%的数据,1<=n<=1000,Li和W都属于[-536870911,536870911]

#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 210000000
using namespace std;
int n;
int ans;
int a[1010];
struct node{
       int x,a,b;
}q[1000000];
int tot;
int cmp(const node &a,const node &b){return a.x<b.x;}
bool find(int x,int a,int b){
     int l=0,r=tot;
     while (l<r){
           int mid=(l + r) >> 1;
           if (q[mid].x<x) l=mid+1;else r=mid;
     }
     while (l<tot && q[l].x==x){
           if (q[l].a==a || q[l].b==a || q[l].a==b || q[l].b==b) l++;else break;
     }
     if (q[l].x!=x) return false;
     return true;
}
int main(){
    freopen("plan.in","r",stdin);
    freopen("plan.out","w",stdout);
    while (scanf("%d",&n)!=EOF){
          if (n==0) break;
          for (int i=1;i<=n;i++){
              scanf("%d",&a[i]);
          }
          ans=-INF;
          tot=0;
          memset(q,0,sizeof(q));
          for (int i=1;i<n;i++){
              for (int j=i+1;j<=n;j++){
                  q[tot].x=a[i]+a[j];
                  q[tot].a=i;
                  q[tot++].b=j;
              }
          }
          sort(q,q+tot,cmp);
          for (int i=1;i<=n;i++){
              for (int j=1;j<=n;j++){
                  if (i!=j){
                            int t=a[i]-a[j];
                            if (find(t,i,j)){
                                         if (a[i]>ans) ans=a[i];
                            }
                  }
              }
          }
          if (ans==-INF) printf("No Solution\n");else
          printf("%d\n",ans);
    }
    return 0;
}

 

Loongint的花篮

【Description】

Loongint要和MM结婚了。在两人的走进礼堂的红地毯两侧,需要摆一些装饰用的花篮,有一些不同高度的花篮,现在这些花篮被Loongint依照自己的美学观念编号为S1,S2,S3…Sn(两侧的花篮高度一样)。可Loongint的MM对这些花篮的摆放方式有不同的看法,她觉得满足以下条件的花篮摆放才是最好的。

如果对于区间[Si,Sj](1<=i<j<=n)中任意的花篮都比Si高且比Sj低,那么这个区间称为一个美学区间。对于所有的美学区间,其长度(定义为j-i)都必须小于等于k,如果有长度大于k的美学区间,MM就会不高兴,Loongint就会有麻烦…

【Input】

第一行为m。表示有m组测试数据。

对于每一组:

第一行n,k,分别表示花篮的数量和美学区间的最大长度。

第二行为n个数,分别表示S1,S2,S3…Sn的值。

【Output】

如果根本不存在美学区间,输出-1。

如果存在美学区间,那么如果任意区间的长度都小于等于k,那么输出最大的长度,否则输出最大长度比k大多少(MaxLength-k)。

【Sample Input】

3

4 2

5 4 3 6

4 1

6 5 4 3

4 2

1 2 3 4

【Sample Output】

1

-1

1

【Hint】

对于30%的测试数据,1<=n<=100。

对于60%的测试数据,1=<n<=5555。

对于100%的测试数据,1<=n<=100000,0<Si<=100000,1=<m<=3。

#include <cstdio>
#include<cmath>
#include <cstring>
#define INF 2000000000
int T;
int n,k;
int a[110000];
//int g[110000][30];
int f[110000][30];
//int gid[110000][30];
int fid[110000][30];
int q[110000];
int len[110000];
int top;
int maxlen;

int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;}
/*
void search(int l,int r){
     if (l==r) return;
     int t=(int)(log10((double)(r-l+1))/log10(2.0));
     int mi,ma;
     if (g[l][t]<g[r-(1 << t)+1][t]) mi=gid[l][t];else mi=gid[r-(1 << t)+1][t];
     if (f[l][t]>f[r-(1 << t)+1][t]) ma=fid[l][t];else ma=fid[r-(1 << t)+1][t];
     if (mi<ma){
                if (ma-mi>maxlen) maxlen=ma-mi;
                if (mi-1>l) search(l,mi-1);
                if (ma+1<r) search(ma+1,r);
     }else
     if (mi>ma){
                if (ma>l) search(l,ma);
                if (mi<r) search(mi,r);
                if (mi-1>ma+1) search(ma+1,mi-1);
     }
}
*/
int main(){
    freopen("baskets.in","r",stdin);
    freopen("baskets.out","w",stdout);
    scanf("%d",&T);
    while (T--){
          scanf("%d%d",&n,&k);
          memset(a,0,sizeof(a));
//          memset(g,0,sizeof(g));
          memset(f,0,sizeof(f));
//          memset(gid,0,sizeof(gid));
          memset(fid,0,sizeof(fid)); 
          memset(q,0,sizeof(q));
          maxlen=0;
          top=0;
          memset(len,0,sizeof(len));
          for (int i=1;i<=n;i++){
              scanf("%d",&a[i]);
//              g[i][0]=a[i];
//              gid[i][0]=i;
              f[i][0]=a[i];
              fid[i][0]=i;
          }
          for (int i=1;i<=n+1;i++){
              while (a[q[top]]>=a[i] && top>0){
                    len[q[top]]=i-1;
                    top--;
              }
              q[++top]=i;
          }
          for (int j=1;j<=(int)(log10((double)n)/log10(2.0));j++)
          for (int i=1;i<=(n-(1 << j)+1);i++){
              /*
              g[i][j]=g[i+(1 << (j-1))][j-1];
              gid[i][j]=gid[i+(1 << (j-1))][j-1];
              if (g[i][j-1]<g[i][j]){
                                     g[i][j]=g[i][j-1];
                                     gid[i][j]=gid[i][j-1];
              }              
              
              g[i][j]=g[i][j-1];
              gid[i][j]=gid[i][j-1];
              if (g[i+(1 << (j-1))][j-1]<g[i][j]){
                         g[i][j]=g[i+(1 << (j-1))][j-1];
                         gid[i][j]=gid[i+(1 << (j-1))][j-1];
              }
              */
              f[i][j]=f[i][j-1];
              fid[i][j]=fid[i][j-1];
              if (f[i+(1 << (j-1))][j-1]>f[i][j]){
                         f[i][j]=f[i+(1 << (j-1))][j-1];
                         fid[i][j]=fid[i+(1 << (j-1))][j-1];
              }
              
//              g[i][j]=min(g[i][j-1],g[i+(1 << (j-1))][j-1]);
//              f[i][j]=max(f[i][j-1],f[i+(1 << (j-1))][j-1]);
          }
          for (int i=1;i<=n;i++){
              int t=(int)(log10((double)(len[i]-i+1))/log10(2.0));
              int ma;
              if (f[i][t]>=f[len[i]-(1 << t)+1][t]) ma=fid[i][t];else ma=fid[len[i]-(1 << t)+1][t];
              if (ma-i>maxlen) maxlen=ma-i;
          }
//          search(1,n);
          if (maxlen==0) printf("-1\n");
          else if (maxlen<=k) printf("%d\n",maxlen);
          else printf("%d\n",maxlen-k);
    }
    return 0;
}

 

Loongint的夜晚

【Description】

Loongint和MM在僻静的小镇上居住着,一天晚上,MM对Loongint说:“亲爱的,去把灯关掉。”Loongint十分兴奋,可发现MM亮了整整一排灯…Loongint必须关掉所有的灯…开始时他站在某一盏灯的旁边,每盏灯都有一个给定功率的电灯泡(!),因为Loongint有着自觉的节能意识(表扬),他希望在耗电能总数最少的情况下将所有的灯关掉。Loongint为了积攒精力,所以只能以1m/s的速度行走。关灯不需要花费额外的时间,因为当他通过时就能将灯关掉。
Loongint需要你在给定路灯设置和灯泡功率的情况下计算以及Loongint的起始位置的情况下关掉所有的灯需耗费的最小能量。

【Input】

输入文件的第一行包含一个整数N,2≤N≤1000,表示灯的数量。
第二行包含一个整数V,1≤V≤N,表示Loongint开始关灯的路灯号码。
接下来的N行中,每行包含两个用空格隔开的整数D和W,用来描述每盏灯的参数,其中0≤D≤1000,0≤W≤1000。D表示该灯与这排灯开始处的距离(用米为单位来表示),W表示灯泡的功率,即在每秒钟该灯泡所消耗的能量数。灯是按顺序给定的。

【Output】

输出文件的第一行即唯一的一行应包含一个整数,即消耗能量之和的最小值。注意结果不超过1,000,000,000。

【Sample Input】

4
3
2 2
5 8
6 1
8 7

【Sample Output】

56

#include <cstdio>
#include <cstring>
int n;
int v;
int f[1100][1100][2];
int d[1100];
int w[1100];
int sum[1100];
int min(int a,int b){return a<b?a:b;}
int main(){
    freopen("night.in","r",stdin);
    freopen("night.out","w",stdout);
    scanf("%d%d",&n,&v);
    for (int i=1;i<=n;i++){
        scanf("%d%d",&d[i],&w[i]);
        sum[i]=sum[i-1]+w[i];
    }
    memset(f,63,sizeof(f));
    f[v][v][0]=f[v][v][1]=0;
    for (int i=v;i>0;i--){
        for (int j=v;j<=n;j++){
            if (i<v){
                     f[i][j][0]=min(f[i][j][0],f[i+1][j][0]+(d[i+1]-d[i])*(sum[n]-sum[j]+sum[i]));
                     f[i][j][0]=min(f[i][j][0],f[i+1][j][1]+(d[j]-d[i])*(sum[n]-sum[j]+sum[i]));
            }
            if (j>v){
                     f[i][j][1]=min(f[i][j][1],f[i][j-1][1]+(d[j]-d[j-1])*(sum[n]-sum[j-1]+sum[i-1]));
                     f[i][j][1]=min(f[i][j][1],f[i][j-1][0]+(d[j]-d[i])*(sum[n]-sum[j-1]+sum[i-1]));
            }
        }
    }
    int ans=f[1][n][0]<f[1][n][1]?f[1][n][0]:f[1][n][1];
    printf("%d\n",ans);
    return 0;
}