9.7训练日志

来源:互联网 发布:淘宝优惠券winppo 编辑:程序博客网 时间:2024/06/05 10:03

9.7训练日志

Curriculum Vitae

Hideo Kojima has just quit his job at Konami. Now he is going to find a new place to work. Despite being such a well-known person, he still needs a CV to apply for a job.

During all his career Hideo has produced n games. Some of them were successful, some were not. Hideo wants to remove several of them (possibly zero) from his CV to make a better impression on employers. As a result there should be no unsuccessful game which comes right after successful one in his CV.

More formally, you are given an array s1, s2, …, sn of zeros and ones. Zero corresponds to an unsuccessful game, one — to a successful one. Games are given in order they were produced, and Hideo can’t swap these values. He should remove some elements from this array in such a way that no zero comes right after one.

Besides that, Hideo still wants to mention as much games in his CV as possible. Help this genius of a man determine the maximum number of games he can leave in his CV.
因为这个第一题,差点创下首次爆0(比赛0分)纪录…这个第一题难度不小,题意是给一串0和1构成数串,要求你删掉一些数据,使1后面没有0,并保证删除数量最小,输出剩余数字个数.我的思路,遍历,遇到1往后遍历看有多少连续的1,再分类取不取这串1(取了1后面0全都gg),记录每个答案输出最大{ps:稍微有点麻烦,不过写起来蛮简单}

#include<bits/stdc++.h>using namespace std;bool cmp(int a,int b){return a>b;}int main() {    int m,a[105],i,ans=0,b=0,c=0,d=0,k0=0,k1=0,x,n=-1,p[101]={0},maxn,f=1;    memset(p,0,sizeof(p));    cin>>m;    ans=m;    for(i=1; i<=m; i++) {        cin>>a[i];        if(a[i]==0)k0++;        else k1++;    }    for(i=1; i<=m; i++) {        if(a[i]==0)             k0--;        else if(a[i]==1) {            b=0;            c=1;            d=0;            for(x=i+1; x<=m; x++) {                if(a[x]==1&&d==0)c++;                else if(a[x]==0) {                    b++;                    d=1;                }                if(d==1&&a[x]==1)break;            }            if(c<=b) {                ans=ans-c;                i=x-1;                k0=k0-b;            } else if(c>=k0) {                ans=ans-k0;                f=0;            } else if(c<k0&&c>b) {                n++;                p[n]=ans-k0;                ans=ans-c;                i=x-1;                k0=k0-b;            }        }        if(f==0)break;    }    if(n>=0)    {sort(p,p+n,cmp);     cout<<max(p[0],ans);    }    else     cout<<ans;}

Math Show

Polycarp takes part in a math show. He is given n tasks, each consists of k subtasks, numbered 1 through k. It takes him tj minutes to solve the j-th subtask of any task. Thus, time required to solve a subtask depends only on its index, but not on the task itself. Polycarp can solve subtasks in any order.

By solving subtask of arbitrary problem he earns one point. Thus, the number of points for task is equal to the number of solved subtasks in it. Moreover, if Polycarp completely solves the task (solves all k of its subtasks), he recieves one extra point. Thus, total number of points he recieves for the complete solution of the task is k + 1.

Polycarp has M minutes of time. What is the maximum number of points he can earn?
n个大任务,包含k个小任务,每个小人要一定时间,完成一个小任务加一分,完成一整个大任务额外加一分,求在给定时间内获得最大分值.
思路,用时间除以完成一整个大任务时间得到最大大任务数,之后从完成0个大任务遍历到最大大任务(数据范围较小因此不会超时)

#include<bits/stdc++.h>using namespace std;int main() {    int n,k,i,x,a[50]= {0},ans[50]= {0},maxn=0;long long int sum=0,m,p,t,c;    cin>>n>>k>>m;    for(i=0; i<k; i++) {        cin>>a[i];        sum+=a[i];    }    sort(a,a+k);    if(m/sum>n)    {cout<<n*(k+1);     return 0;    }    else p=m/sum;    for(i=0; i<=p; i++) {        t=m-sum*i;        c=n-i;        ans[i]+=(k+1)*i;        if(t==0||c==0)break;        for(x=0; x<k; x++) {            if(t>=c*a[x]) {                ans[i]+=c;                t=t-c*a[x];            }             else while(t>=a[x]) {                    ans[i]++;                    t=t-a[x];                }            if(t<a[x])break;            }        //cout<<ans[i]<<endl;    }    for(i=0;i<=p;i++)     maxn=max(maxn,ans[i]);     cout<<maxn;}

Four Segments

You are given an array of n integer numbers. Let sum(l, r) be the sum of all numbers on positions from l to r non-inclusive (l-th element is counted, r-th element is not counted). For indices l and r holds 0 ≤ l ≤ r ≤ n. Indices in array are numbered from 0.

For example, if a = [ - 5, 3, 9, 4], then sum(0, 1) =  - 5, sum(0, 2) =  - 2, sum(1, 4) = 16 and sum(i, i) = 0 for each i from 0 to 4.

Choose the indices of three delimiters delim0, delim1, delim2 (0 ≤ delim0 ≤ delim1 ≤ delim2 ≤ n) and divide the array in such a way that the value of res = sum(0, delim0) - sum(delim0, delim1) + sum(delim1, delim2) - sum(delim2, n) is maximal.

Note that some of the expressions sum(l, r) can correspond to empty segments (if l = r for some segment).
较难,一串数,找三个点将它分成四个集合a,b,c,d,要求a-b+c-d值最大,输出三个点.
思路:模拟即可,需要注意先遍历第二个点,复杂度只有o(n^2),如果先遍历1或3则会有o(n^3)…

#include<bits/stdc++.h>using namespace std;int main(){long long int n,a[5005]={0},b[5005]={0},i,j,x,d1,d2,d3,n1,n2,k1,k2,c[5005]={0},p1[5005]={0},p2[5005]={0},p3[5005]={0},maxn=0;cin>>n;for(i=0;i<n;i++) {cin>>a[i];  if(i==1)b[i]=a[0];   else if(i!=1&&i!=0)b[i]=b[i-1]+a[i-1]; } b[n]=b[n-1]+a[n-1]; for(i=0;i<=n;i++)  {d2=i;k1=0;k2=0;n1=0,n2=i;    for(j=0;j<=i;j++)    {if(2*b[j]-b[i]>=k1)     {n1=j;k1=2*b[j]-b[i];     }    }   for(x=i;x<=n;x++)    {if(2*b[x]-b[n]-b[i]>=k2)      {n2=x;k2=2*b[x]-b[n]-b[i];      }     }      c[i]=k1+k2;     p1[i]=n1;     p2[i]=d2;     p3[i]=n2;  }  for(i=0;i<=n;i++)   {if(c[i]>=c[maxn])maxn=i;   }   cout<<p1[maxn]<<" "<<p2[maxn]<<" "<<p3[maxn]<<endl;   //cout<<c[maxn]<<endl;}

Monitor

Recently Luba bought a monitor. Monitor is a rectangular matrix of size n × m. But then she started to notice that some pixels cease to work properly. Luba thinks that the monitor will become broken the first moment when it contains a square k × k consisting entirely of broken pixels. She knows that q pixels are already broken, and for each of them she knows the moment when it stopped working. Help Luba to determine when the monitor became broken (or tell that it’s still not broken even after all q pixels stopped working).
难题,一个n*m的电视,在某些时间某些点会坏,如果坏成1个k乘k的正方形电视就炸了,求炸的最小时间,不会炸输出-1.
思路,先遍历行,在遍历列,一起遍历会超时..

#include<bits/stdc++.h>using namespace std;int a[555][555],s,q,n,m,ans,inf;int f(int w,int x,int y){    int t=0;    for (int i=x;i<=y;i++){        t=max(t,a[w][i]);    }    return t;}int main(){    scanf("%d%d%d%d",&n,&m,&s,&q);    memset(a,126,sizeof a);    ans=inf=a[0][0];    int x,y,z;    for (;q--;){        scanf("%d%d%d",&x,&y,&z);        a[x][y]=z;    }    for (int k=1;k<s;k++){        for (int i=1;i<n;i++){            for (int j=1;j<=m;j++){                a[i][j]=max(a[i][j],a[i+1][j]);            }        }    }    for (int i=1;i+s-1<=n;i++){        for (int j=1;j+s-1<=m;j++){            ans=min(ans,f(i,j,j+s-1));        }    }    printf("%d\n",ans==inf?-1:ans);}

Chemistry in Berland

Igor is a post-graduate student of chemistry faculty in Berland State University (BerSU). He needs to conduct a complicated experiment to write his thesis, but laboratory of BerSU doesn’t contain all the materials required for this experiment.

Fortunately, chemical laws allow material transformations (yes, chemistry in Berland differs from ours). But the rules of transformation are a bit strange.

Berland chemists are aware of n materials, numbered in the order they were discovered. Each material can be transformed into some other material (or vice versa). Formally, for each i (2 ≤ i ≤ n) there exist two numbers xi and ki that denote a possible transformation: ki kilograms of material xi can be transformed into 1 kilogram of material i, and 1 kilogram of material i can be transformed into 1 kilogram of material xi. Chemical processing equipment in BerSU allows only such transformation that the amount of resulting material is always an integer number of kilograms.

For each i (1 ≤ i ≤ n) Igor knows that the experiment requires ai kilograms of material i, and the laboratory contains bi kilograms of this material. Is it possible to conduct an experiment after transforming some materials (or none)?
实验室要一些药品,每个药品有各自需求量,实验室不足,只能通过反应转化,而序号i的东西只能与序号小于i的东西互相转化,输出能否转化成功.
从后向前遍历,多的转化掉,少的补,贪心.

#include<bits/stdc++.h>#define ll long long intusing namespace std;double b[100005]={0},a[100005]={0};int x,k,c[100005],d[100005];int main(){int n,i;cin>>n;for(i=1;i<=n;i++)cin>>b[i];for(i=1;i<=n;i++) {cin>>a[i];  a[i]=b[i]-a[i]; }for(i=2;i<=n;i++)cin>>c[i]>>d[i];for(i=n;i>=2;i--) {if(a[i]<0)   {a[c[i]]=a[c[i]]+(a[i]*d[i]);    a[i]=0;   } else if(a[i]>=0)   {a[c[i]]+=a[i];    a[i]=0;     }   }for(i=1;i<=n;i++) if(a[i]<0) {cout<<"NO";return 0; }cout<<"YES"; }

Random Query

You are given an array a consisting of n positive integers. You pick two integer numbers l and r from 1 to n, inclusive (numbers are picked randomly, equiprobably and independently). If l > r, then you swap values of l and r. You have to calculate the expected value of the number of unique elements in segment of the array from index l to index r, inclusive (1-indexed).
有点难懂,老师解释后才理解啥米是期望(高一数学必修一我们还没学),大概是个与平均值类似的玩意..理解后写一个数组存出现过的数,概率相加之后除以可能情况数即可

#include<bits/stdc++.h>using namespace std;int a[1000050]={0};int main(){int n,i,b;long long int ans;cin>>n;ans=-n;for(i=1;i<=n;i++) {cin>>b;  ans+=(long long int)(i-a[b])*(n-i+1)<<1;  a[b]=i; } printf("%.12lf",(double)ans/((double)n*n));}

总结:

代码算法建立在数学基础上,数学方面也要努力!

原创粉丝点击