3 条题解
-
1
很明显这道题是一个差分题,但是要求我们判断断裂数组的最小时间,一个暴力的想法是每次都在轰炸的地方加上对应的杀伤力,如果有一个位置的杀伤力>=m,就输出对应的秒数,但是这种方法的时间复杂度为O(n^2),数据给的范围是1e5,我们可以想办法把他优化到O(nlogn),不妨换个角度思考,从答案的角度来看,我们需要找到一个最小数,也就是说答案可以理解为是递增的,根据logn的复杂度我们可以想到二分查找,即对答案进行二分查找,这样我们二分答案然后差分数组,就能得到时间复杂度为O(nlogn)的算法。 代码如下:
#include<bits/stdc++.h> using namespace std; const int maxv=1e5+10; #define ll long long ll n,m,lefts[maxv],rights[maxv],values[maxv],arr[maxv]={0}; bool judge(int time){ memset(arr,0,sizeof(arr));//重置数组值为0 //此处差分为 for(int i=0;i<time;i++){ arr[lefts[i]]+=values[i]; arr[rights[i]+1]-=values[i]; } ll maxv=*max_element(rights,rights+time);//找右边界最大值,缩短差分长度 //还原数组 for(int i=1;i<=maxv;i++){ arr[i]+=arr[i-1]; if(arr[i]>=m)return 1;//如果找到就返回true } return 0;//否则返回false } int main(){ ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0); cin>>n>>m; for(int i=0;i<n;i++){ cin>>lefts[i]>>rights[i]>>values[i]; } int l=0,r=n; //二分答案,此处为左闭右闭写法 //int ans=0; while(l<=r){ int mid=l+(r-l)/2; if(judge(mid)){ //ans=mid若分不清l是答案还是r是答案可以再开一个ans记录 r=mid-1; }else{ l=mid+1; } } if(l<=n)cout<<l;//若没有找到那么l一定会越界 else cout<<"impossible"; return 0; }
时间复杂度O(nlogn); 空间复杂度O(n); 希望我的题解对你有帮助!
信息
- ID
- 965
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 708
- 已通过
- 66
- 上传者