我做了9次,终于AC了!!!!
由于第一次太过久远,所以我就说说今天提交的这几次:
首先我想直接一层一层的做减法,但是忽略了不同田地长度不同,所以这个代码只有5分,这个算法来来回回修改并提交了4次,全部都只有5分。
第二次我想既然最少k天完成,那么我就直接将减少到只有k天的总能量求出来,如果m大于这个能量值,那么就可以知道答案就是k,如果不是,就需要运用贪心算法,每次加上所有除去原先长度小于等于k的一层所需要的能量之和,但是这里我没有考虑到可能有的田地长度会溢出,就是说,假设其原长度为k1,但是我一直往上叠加,可能超过田地原本的长度,所以失败了,通过了15%,这个代码提交了2次,后面想放弃,但是想了想,既然问题都找到了,那么就继续写!!!
第三次我运用了一个for循环,每次累加层数之后查找满足第二次失败原因的元素,如果成立,就将这一个田地从原先的累加存值中删掉,然后继续进行同样的操作,虽然这次思路是对的,但是超时了,只通过了70%,超时的原因是for循环,总共提交了2次。
第四次,因此我发明了以下算法(清华北大的数据结构书中是没有的)我直接建立一个vector的二维数组和一个check字符串,用于检测这个长度是否存在一个田与之相等,因为考虑到可能有多个田长度相同,所以每一次检测到相同长度的田地,那么这个vector数组相应位置的大小就要加一,并且存储增加一格需要的能量,这样就可以在进行第二次提交的修补时在数据较大时将复杂度降低数十万倍,直接将数据处理能力提高了一个档次。
源代码:
#include<iostream>
#include<vector>
using namespace std;
#define Max_size 100003
long long n,m,k;
bool check[Max_size]={0};
typedef vector<int> A;
typedef vector<A> B;
B sav;
vector<long long>time;
vector<long long>cut;
void change(long long *sum,long long ans){
if(check[ans]==1){
for(int i=0;i<sav[ans].size();i++){
*sum-=sav[ans][i];
}
}
}
int main()
{
cin>>n>>m>>k;
long long sum=0,sum1=0;
long long ans=0;
time.resize(n);
cut.resize(n);
sav.resize(Max_size);
for(int i=0;i<n;i++){
cin>>time[i]>>cut[i];
check[time[i]]=1;
sav[time[i]].resize(sav[time[i]].size()+1);
sav[time[i]][sav[time[i]].size()-1]=cut[i];
if(time[i]>k){
sum+=cut[i]*(time[i]-k);
sum1+=cut[i];
}
}
if(sum<-m){
cout<<k<<endl;
return 0;
}
else{
long long t=sum-m;
ans=k;
while(t>0){
t-=sum1;
ans+=1;
change(&sum1,ans);
}
cout<<ans<<endl;
return 0;
}
/*
sum指的是将时间缩短到k天的最少所需,
sum1指的是将每一个被缩短过的农田加一可以带来的补偿
有两种情况:
第一,用sum减去m表示需要赔偿的肥力,
这个肥力的大小可能可以整除
*/
}