Codeforecs-1260D
D. A Game with Traps
题目大意:
有一条线,线上有k个陷阱,但是你可以走到r来除去这个陷阱,士兵的敏捷值小于这个陷阱的危险程度的会死在这个陷阱,现在给你一组士兵,问你t秒内最多可以将多少个士兵移动到终点
题目链接 :https://codeforces.com/contest/1260/problem/D
解题思路:先将士兵的敏捷值排序,然后二分士兵敏捷值的最小值,即可得出答案,
我们实际上应该如何将士兵带到老板那里? 实际上,可以影响小队的每个陷阱都可以视为一个区[li,ri],这样我们的小队就无法移动到li,直到我们移至ri并解除该陷阱的武装。 我们应该走过这三段路:第一次是在没有小队的情况下向前走以解除陷阱的武装,第二次是向后走以返回小队,第三次是与小队一起前进。 因此,我们必须花费的总时间可以计算为n + 1 + 2T,其中T是属于至少一个陷阱段的单位段的数量-可以使用事件处理算法或段联合来计算。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=3e5+10; int a[maxn]; vector<pair<pair<int,int>,int> >q; int m,n,k,t; bool judge(int x) { if(x==0) return true; int ans=n+1,minn=a[m-x+1]; int l=0,r=-1; for(int i=0;i<q.size();i++) { if(q[i].second>minn) { if(r<q[i].first.first) { ans+=2*(r-l+1); l=q[i].first.first; r=q[i].first.second; } else r=max(r,q[i].first.second); } } ans+=2*(r-l+1); if(ans<=t) return true; else return false; } int main() { cin>>m>>n>>k>>t; for(int i=1;i<=m;i++) cin>>a[i]; sort(a+1,a+1+m); for(int i=0;i<k;i++) { int a,b,c; cin>>a>>b>>c; q.push_back(make_pair(make_pair(a,b),c)); //cin>>q[i].first.first>>q[i].first.second>>q[i].second; } sort(q.begin(),q.end()); int l=0,r=m,ans=0; while( l<=r ) { int mid=(l+r)>>1; if( judge(mid) ) { l=mid+1; ans=mid; } else r=mid-1; } cout<<ans<<endl; return 0; }