zoukankan      html  css  js  c++  java
  • 2016.6.10测试

    1、汽艇(Boat.cpp/c/pas)
    【问题描述】
    有 n 个人要去坐 1 汽艇,每个人单独坐汽艇的快乐程度是 Ci,每多一个人,他的快乐程度会减去 Di,请求出使快乐程度之和达到最大的方案。(假设汽艇的容量足够大)。
    【输入格式】
    输入文件共有 3 行:
    第1 行是一个整数 n;
    第2 行有n 个整数,依次表示每个人单独坐汽艇的快乐程度 Ci(1<=Ci<=10000);
    第3 行有n 个整数,依次表示每多 1 人,每个人快乐程度的下降值 Di(1<=Di<=10)。
    【输出格式】
    应输出两行:
    第1 行一个整数,是最大的快乐程度之和;
    第2 行一个整数,是最大的快乐程度之和所对应的汽艇上的人数(若有多种方案,则输出人数最多的)。
    【输入样例】
    6
    10 10 10 10 10 9
    2 2 2 2 2 3
    【输出样例】
    18
    3
    【样例说明】
    前 3 个人去坐汽艇可使快乐程度之和达到最大,每个人的快乐程度均为 10-2*2=6,总和是
    18。
    【数据范围】
    对于 30%的数据,n<=20;
    对于 100%的数据,n<=1000。

    正解:贪心

    解题报告:

      标准水题,枚举有多少个人,然后每次sort,取最优的情况即可。  

     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 #ifdef WIN32   
    14 #define OT "%I64d"
    15 #else
    16 #define OT "%lld"
    17 #endif
    18 using namespace std;
    19 typedef long long LL;
    20 const int MAXN = 1011;
    21 int n,ans,cnt,jilu;
    22 
    23 struct node{
    24     int val;
    25     int fall;
    26 }a[MAXN];
    27 
    28 struct now{
    29     int val;
    30 }jump[MAXN];
    31 
    32 inline int getint()
    33 {
    34        int w=0,q=0;
    35        char c=getchar();
    36        while((c<'0' || c>'9') && c!='-') c=getchar();
    37        if (c=='-')  q=1, c=getchar();
    38        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
    39        return q ? -w : w;
    40 }
    41 
    42 inline bool cmp(node q,node qq){ return q.val>qq.val; }
    43 
    44 inline bool ccmp(now q,now qq){ return q.val>qq.val; }
    45 
    46 inline void solve(){
    47     n=getint();
    48 
    49     for(int i=1;i<=n;i++) a[i].val=getint();
    50 
    51     for(int i=1;i<=n;i++) a[i].fall=getint();
    52 
    53     sort(a+1,a+n+1,cmp); ans=a[1].val; jilu=1;
    54     for(int i=2;i<=n;i++) {
    55     for(int j=1;j<=n;j++) jump[j].val=a[j].val-(i-1)*a[j].fall;
    56     sort(jump+1,jump+n+1,ccmp);
    57     cnt=0;
    58     for(int j=1;j<=i;j++)  cnt+=jump[j].val;
    59     if(cnt>=ans) {
    60         ans=cnt;
    61         jilu=i;
    62     }
    63     }
    64     printf("%d
    %d",ans,jilu);
    65 }
    66 
    67 int main()
    68 {
    69   solve();
    70   return 0;
    71 }


    2、上网(net.cpp/c/pas)

    【问题描述】
    假设有 n 个人要上网,却只有 1 台电脑可以上网。上网的时间是从 1 szw 至 T szw ,szw是一个自创的时间单位,至于 szw怎么换算成 s,min 或 h,没有人清楚。依次给出每个人在某个时间段内上网的快乐程度 C(必须这个人在整个时间段内都在上网,才能获得快乐程度C,否则,快乐程度是 0),请你得到使总的快乐程度达到最大的方案。
    【输入格式】
    第1 行2 个整数 n和 T,含义如题目所述;
    接下来有 n 个这样的结构(每两个相邻的结构之间有一空行,且第 1 个结构和第一行间有
    一空行):
    第1 行一个整数 Mi,表示第 i 个人的时间段的个数;
    接下来有 Mi 行,每行3个整数 Xj,Yj,C,表示第 i个人在[Xj,Yj]内上网的快乐程度为 C,
    因此有 Xj-Yj-1=1,X1=1,Ymi=T,Xj<=Yj。
    【输出格式】
    仅输出一行,为总的最大的快乐程度。
    【输入样例】
    3 10
    3
    1 3 6
    4 7 9
    8 10 3
    3
    1 3 5
    4 7 10
    8 10 1
    4
    1 3 2
    4 8 2
    9 9 6
    10 10 3
    【输出样例】
    25
    【样例说明】
    在[1,3]内,安排 1 上网,快乐程度为 6;
    在[4,7]内,安排 2 上网,快乐程度为 10; 在[8,8]内,不安排;
    在[9,9]内,安排 3 上网,快乐程度为 6;
    在[10,10]内,安排 3 上网,快乐程度为 3;
    这是使总的快乐程度达到最大的方案,对应的值是 25。
    【数据范围】
    对于 30%的数据,n<=4,所有的 Mi<=5,T<=20;
    对于 60%的数据,n<=100,所有的 Mi<=100,T<=2000;
    对于 100%的数据,n<=500,所有的 Mi<=500,T<=500000,所有的 0<C<=10^9,并保证最终解 Max<=10^9。

    正解:DP

    解题报告:

      这道题我开始居然想了很久,我真是太菜了。。。

      果断DP,每个人的各段区间没有任何区别,直接丢一起按照左端点排序。题目可转化为给定若干带权区间,取出不重叠的区间使权值最大。

      貌似大家都是在做区间数的做法。。。我是直接讨论时间,for时间,然后记录一下处理到哪段区间,并且当前的最左端点,一维DP

     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 #ifdef WIN32   
    14 #define OT "%I64d"
    15 #else
    16 #define OT "%lld"
    17 #endif
    18 using namespace std;
    19 typedef long long LL;
    20 const int MAXN = 511;
    21 const int MAXT = 500011;
    22 int n,tim;
    23 int m[MAXN];
    24 int cnt;
    25 int f[MAXT];//f[i]表示i时刻(含)之前的最大值
    26 
    27 struct seq{
    28     int l,r,val;
    29 }a[MAXN*MAXN],jump[MAXN*MAXN];
    30 
    31 inline int getint()
    32 {
    33        int w=0,q=0;
    34        char c=getchar();
    35        while((c<'0' || c>'9') && c!='-') c=getchar();
    36        if (c=='-')  q=1, c=getchar();
    37        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
    38        return q ? -w : w;
    39 }
    40 
    41 inline bool cmp(seq q,seq qq){ if(q.l==qq.l) return q.r<qq.r;  return q.l<qq.l;   }
    42 
    43 int main()
    44 {
    45   n=getint(); tim=getint();
    46   for(int i=1;i<=n;i++) {
    47       m[i]=getint();
    48       for(int j=1;j<=m[i];j++) {
    49       a[++cnt].l=getint();
    50       a[cnt].r=getint();
    51       a[cnt].val=getint();
    52       }
    53   }
    54 
    55   sort(a+1,a+cnt+1,cmp);
    56 
    57   int ji=1,nowl=a[1].l;
    58   //f[a[1].r]=a[1].val;
    59   for(int i=1;i<=tim;i++) {
    60       f[i]=max(f[i-1],f[i]);
    61       if(i<nowl) continue;
    62       while(a[ji].l==nowl && ji<=cnt) f[a[ji].r]=max(f[a[ji].r],f[i-1]+a[ji].val),ji++;
    63       nowl=a[ji].l;
    64   }
    65 
    66   printf("%d",f[tim]);
    67   return 0;
    68 }


    3、集合(gather)
    【问题描述】
    小明总喜欢做一些与众不同的事情,最近他迷上了集合运算。他觉得光是简单的预算不过瘾,所以他把2个集合运算集合起来。由于小明很喜欢区间运算。于是他定义了一个这样的值。
    你N个各不相同的区间,请你从中找出若干个区间使其权值最大。
    W=|A1∪A2∪……∪AK|*|A1∩A2∩……AK|
    其中{A1,A2……AK}(K>1,Ai<>Aj{i<>j})
    如果这些区间没有交集则权值为0,给你N个各不相同的区间,请你从中找出若干个区间使其权值最大,并告诉小明。
    【输入文件】
    第一行N
    接下来N行 l r(1<=l<r<=10^6)
    【输出文件】
    最大权值
    【输入样例】
    4
    1 6
    4 8
    2 7
    3 5
    【输出样例】
    24
    【数据约定】
    10% N<=10
    30% N<=2*10^4
    50% N<=10^5
    100% 1<N<=10^6

    正解:决策单调性

    解题报告:

      考场上明明想出来了,一定是两个的时候最优,但是自己不相信自己,而且感觉n^2的暴力也会TLE就没打,打了一个大暴力,水到20分。

      等我打完大暴力,心血来潮make数据发现永远是2个的时候最优。。。追悔莫及。。。

      显然直接两两枚举会TLE,就要考虑优化。

      题解说 用决策单调性,有一些奇奇怪怪的性质。传送门:http://www.cnblogs.com/chenyushuo/p/5261657.html

      这道题居然是BZOJ原题,出题人真懒。

      先贴一发大暴力:

      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #include <set>
     13 #ifdef WIN32   
     14 #define OT "%I64d"
     15 #else
     16 #define OT "%lld"
     17 #endif
     18 using namespace std;
     19 typedef long long LL;
     20 const int MAXN = 1000011;
     21 int n;
     22 bool pd[MAXN];
     23 int ans;
     24 
     25 struct seq{
     26     int l,r;
     27 }a[MAXN],dui[MAXN];
     28 
     29 inline int getint()
     30 {
     31        int w=0,q=0;
     32        char c=getchar();
     33        while((c<'0' || c>'9') && c!='-') c=getchar();
     34        if (c=='-')  q=1, c=getchar();
     35        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     36        return q ? -w : w;
     37 }
     38 
     39 inline bool cmp(seq q,seq qq){
     40     if(q.l==qq.l) return q.r<qq.r;
     41     return q.l<qq.l;
     42 }
     43 
     44 inline void check(int cnt){
     45     if(cnt==0 || cnt==1) return ;
     46     int total=0;
     47     for(int i=1;i<=n;i++) if(pd[i]) dui[++total]=a[i];
     48     sort(dui+1,dui+total+1,cmp);
     49     int head=dui[1].l,tail=dui[1].r;
     50     int maxl=0;
     51     for(int i=1;i<=total;i++) head=max(head,dui[i].l),tail=min(tail,dui[i].r);
     52     if(head>=tail) return;
     53     maxl=tail-head;
     54 
     55     int nowl=dui[1].l,nowr=dui[1].r;
     56     int ji=0; ji=nowr-nowl;
     57     for(int i=2;i<=total;i++) {
     58     if(dui[i].l==nowl) ji+=dui[i].r-nowr,nowr=dui[i].r;
     59     else{ 
     60         nowl=dui[i].l; 
     61         if(nowl>nowr)  {
     62         ji+=dui[i].r-dui[i].l; 
     63         nowr=dui[i].r;
     64         }
     65         else{
     66         if(dui[i].r>nowr) {
     67             ji+=dui[i].r-nowr;
     68             nowr=dui[i].r;
     69         }
     70         }
     71     }
     72     }
     73     maxl*=ji;
     74     if(maxl>ans) {
     75     ans=maxl;
     76     /*for(int i=1;i<=n;i++)
     77         if(pd[i])
     78         printf("%d ",i);
     79         printf("
    %d 
    ",ans);*/
     80     }
     81 }
     82 
     83 inline void dfs(int now,int cnt){
     84     if(now==n+1) {  check(cnt);return ; }
     85     pd[now]=1; dfs(now+1,cnt+1);
     86     pd[now]=0; dfs(now+1,cnt);
     87 }
     88 
     89 inline void solve(){
     90   n=getint();
     91   for(int i=1;i<=n;i++) a[i].l=getint(),a[i].r=getint();
     92 
     93   dfs(1,0);
     94 
     95   printf("%d",ans);
     96 }
     97 
     98 int main()
     99 {
    100   solve();
    101   return 0;
    102 }

    正解:单调队列+单调栈

      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #include <set>
     13 #ifdef WIN32   
     14 #define OT "%I64d"
     15 #else
     16 #define OT "%lld"
     17 #endif
     18 using namespace std;
     19 typedef long long LL;
     20 const int MAXN = 1000011;
     21 int n,cnt;
     22 LL ans;
     23 
     24 struct seq{
     25     int l,r;
     26 }a[MAXN];
     27 
     28 inline LL calc(const seq &j,const seq &i){return 1LL*(i.r-j.l)*(j.r-i.l);}
     29 
     30 inline int getint()
     31 {
     32        int w=0,q=0;
     33        char c=getchar();
     34        while((c<'0' || c>'9') && c!='-') c=getchar();
     35        if (c=='-')  q=1, c=getchar();
     36        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     37        return q ? -w : w;
     38 }
     39 
     40 inline bool cmp(seq q,seq qq){
     41     if(q.l==qq.l) return q.r>qq.r;
     42     return q.l<qq.l;
     43 }
     44 
     45 inline LL max(LL pp,LL ppp){ if(pp<ppp) return ppp; return pp; }
     46 
     47 struct stac{
     48     int pos,top;
     49     struct data{
     50     int l,r,id;
     51     }lin,sta[MAXN];
     52     inline void init(){ sta[top=1]=(data){2,n,1}; pos=1; }
     53     bool comp(int xx,int x,int y){return calc(a[x],a[xx])<calc(a[y],a[xx]);}
     54     inline int get(int id){
     55     int l=lin.l,r=lin.r,bian=lin.id;
     56     int mid;
     57     while(l<r) {
     58         mid=(l+r)/2+1;
     59         if(comp(mid,bian,id)) l=mid; else r=mid-1;
     60     }
     61     return l;
     62     }
     63     inline void push(int id){
     64     while(top && !comp(sta[top].l,sta[top].id,id)) top--;
     65     lin=sta[top--];
     66     int m=get(id);
     67     if(lin.l<=m) sta[++top]=(data){lin.l,m,lin.id};
     68     if(m<n) sta[++top]=(data){m+1,n,id};
     69     }
     70     inline LL query(int x){
     71     while(x>sta[pos].r) pos++;
     72     return calc(a[sta[pos].id],a[x]);
     73     }
     74 }stack;
     75 
     76 struct queue{//单调队列,维护一个左端点、右端点坐标都单调递增,长度单调递减的区间队列
     77     int head,tail;
     78     struct data{
     79     int r,len;
     80     }seq[MAXN],lin;
     81     inline void push(int id){
     82     lin=(data){a[id].r,a[id].r-a[id].l};
     83     while(head<=tail && seq[tail].len<=lin.len) tail--;
     84     seq[++tail]=lin;
     85     }
     86     inline LL query(int id){
     87     int r=a[id].r;
     88     while(head<=tail && seq[head].r<r) head++;
     89     if(head<=tail) return seq[head].len;
     90     else return -1;
     91     }
     92 }que;
     93 
     94 inline void solve(){
     95     n=getint();
     96     for(int i=1;i<=n;i++) a[i].l=getint(),a[i].r=getint();
     97 
     98     sort(a+1,a+n+1,cmp);
     99     int last=0;
    100     que.head=1;
    101     for(int i=1;i<=n;i++) {
    102     if(a[i].r>last) last=a[i].r,a[++cnt]=a[i],que.push(i);//得到去掉互相包含之后的新区间集,并加入单调队列,更新当前最右的端点值
    103     else ans=max( que.query(i)*(a[i].r-a[i].l) , ans );//计算互相包含的情况
    104     }
    105 
    106     stack.init();
    107     for(int i=2;i<=cnt;i++) {
    108     ans=max(ans,stack.query(i)),stack.push(i);
    109     }
    110 
    111     printf(OT,ans);
    112 }
    113 
    114 int main()
    115 {
    116   solve();
    117   return 0;
    118 }


    4、新斯诺克(snooker.cpp/c/pas)
    【问题描述】
    斯诺克又称英式台球,是一种流行的台球运动。在球桌上,台面四角以及两长边中心位置各有一个球洞,使用的球分别为 1 个白球,15 个红球和 6 个彩球(黄、绿、棕、蓝、粉红、黑)共22个球。击球顺序为一个红球、一个彩球直到红球全部落袋,然后以黄、绿、棕、蓝、粉红、黑的顺序逐个击球,最后以得分高者为胜。斯诺克的魅力还在于可以打防守球, 可以制造一些障碍球使对方无法击打目标球而被扣分。正是因为这样,斯诺克是一项充满神奇的运动。 现在考虑这样一种新斯诺克,设母球(母球即是白球,用于击打其他球)的标号为M,台面上有 N 个红球排成一排,每一个红球都有一个标号,`他们的标号代表了他们的分数。 现在用母球击打这些红球,一杆击打,如果母球接触到红球,就称为“K 到红球”。我们假设,一次可以击打任意多相邻连续的红球,也可以只击打一个球。并且红球既不会落袋,也不会相互发生碰撞,而只是停留在原处。每次击打时候,要想“K到红球”,至少要击打一个红球,如果想一次击打多个红球,那么击打的红球必须是依次连续排列的。 如果一次 “K 到红球”所有红球的标号之和的平均数大于母球的标号M,就获得了一个 “连击”。 现在请你计算总共能有多少种“连击”方案。
    注意:如果当前有标号为 1、2、3的三种红球,母球标号为 0, 有如下 6 种获得“连击”方案: (1) 、 (2) 、 (3) 、 (1,2) 、 (2,3) 、 (1,2,3)
    【输入文件】
    输入文件共有两行,第一行是 N,M (N<=100000,M<=10000),
    N 表示台面上一共有 N 个红球,M 表示母球的标号。
    第二行是 N 个正整数,依次表示台面上 N 个红球的标号,所有标号均不超过10000。
    【输出文件】
    输出文件只有一个数,为“连击”的方案总数。
    【输入样例】
    4 3
    3 7 2 4
    【输出样例】
    7

    正解:归并排序,逆序对 

    解题报告:

      刚看到这道题就想到POJ上刷的那道求序列的最大平均值的神题,那个是用斜率优化、凸包优化的DP,结果发现跟这道题并没有关系,被小胖犇狠狠嘲讽了一波。

      静下心来推导了一波。发现一个神奇的性质:一个区间[i,j]满足条件当且仅当(前缀和)(sum[j]-sum[i-1])/(j-i) > m,移项:(sum[j]-sum[i-1])>(j-i)*m。。。高兴地发现这就是一个逆序对。。。

      直接归并排序,求前缀和的逆序对。

     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 #ifdef WIN32   
    14 #define OT "%I64d"
    15 #else
    16 #define OT "%lld"
    17 #endif
    18 using namespace std;
    19 typedef long long LL;
    20 const int MAXN = 100011;
    21 int n,m;
    22 int sum[MAXN],a[MAXN],jump[MAXN];
    23 int g[MAXN];
    24 LL ans;
    25 
    26 inline int getint()
    27 {
    28        int w=0,q=0;
    29        char c=getchar();
    30        while((c<'0' || c>'9') && c!='-') c=getchar();
    31        if (c=='-')  q=1, c=getchar();
    32        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
    33        return q ? -w : w;
    34 }
    35 
    36 inline void merge(int l,int mid,int r){
    37     int i=l,j=mid+1;
    38     int cnt=l;
    39     while(i<=mid && j<=r) {
    40     if(jump[i]<=jump[j])  g[cnt++]=jump[i++];
    41     else{
    42         g[cnt++]=jump[j++];
    43         //ans+=mid-i+1;
    44         ans+=(LL)mid; ans-=(LL)i; ans++;
    45     }
    46     }
    47     while(i<=mid) g[cnt++]=jump[i++];
    48     while(j<=r) g[cnt++]=jump[j++];
    49     //for(;i<=mid;i++) g[cnt++]=a[i];
    50     //for(;j<=r;j++) g[cnt++]=a[i];
    51     for(i=l;i<=r;i++) jump[i]=g[i];
    52 }
    53 
    54 inline void gui(int l,int r){
    55     if(l==r) return ;
    56     int mid=(l+r)/2;
    57     gui(l,mid); gui(mid+1,r);
    58     merge(l,mid,r);
    59 }
    60 
    61 inline void solve(){
    62     n=getint();m=getint();
    63     for(int i=1;i<=n;i++) {
    64     a[i]=getint(); sum[i]=sum[i-1]+a[i];
    65     jump[i]=sum[i]-m*i;
    66     }
    67     for(int i=1;i<=n;i++) jump[i]=-jump[i];//正序对变成逆序对
    68 
    69     gui(0,n);
    70     
    71     printf(OT,ans);
    72 }
    73 
    74 int main()
    75 {
    76   solve();
    77   return 0;
    78 }
  • 相关阅读:
    mysql常用基本命令
    mysql8.0.13下载与安装图文教程
    k8s ingress 增加跨域配置
    Jenkins 备份恢复插件 thinBackup 使用
    k8s HA master 节点宕机修复
    nginx 跨域问题解决
    mongodb 3.4.24 主从复制
    k8s 线上安装 jenkins并结合 jenkinsfile 实现 helm 自动化部署
    k8s helm 运用与自建helm仓库chartmuseum
    centos6 源码安装 unzip
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5573620.html
Copyright © 2011-2022 走看看