题意:
x正轴上有着一个陷阱的位置,开关和灵敏度,如果一个士兵灵敏度输给陷阱,他是过不去这个陷阱的
幸运的是,你可以先过去把开关给关了,没错你是不怕陷阱的
接下来呢你有操作,你移动一个,耗费一秒
而你的团队需要你一起才能移动,但是团队有一个士兵过不了,那就不能过去,你可以先过去关掉开关,然后再回来带领你的团队过去
思路:
一开始就想到二分找最多人数,然后贪心来走路满足t秒内。
问题是怎么贪心呢?
我们不难发现我们关完开关后再回到队伍里一起走,所以我们要尽可能的减少这种往回。
图书一画图就发现,我们以陷进位置和开关位置连起来看作一个线段,两个线段相交,答案贡献就是2*(关掉第一个后顺手关第二个)
线段不相交就发现,例如(2,3)(5,10)你当然不可以关完3后还去关10,因为这样你就沙雕了,你回来的时候又通过来3 5,这是没必要的
所以对于不是相交的,我们走到3后就不用顺手帮5走到10了。
#include<bits/stdc++.h> using namespace std; const int maxx=2e5+10; int l[maxx],r[maxx],d[maxx],a[maxx]; int n,m,k,t; vector<pair<int,int> >v[maxx]; int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } bool cmp(int a,int b){return a>b;} int work(int x) { int tmpp=1,pre=0;// printf("hhx :: %d\n",x); for(int i=1;i<=n;i++) { int maxx=-1; // for(vector<pair<int,int> >::iterator it=v[i].begin();it!=v[i].end();it++) for(auto it:v[i]) if(it.second>x) maxx=max(maxx,it.first); if(~maxx) { pre=max(pre,i-1); if(pre<maxx) tmpp+=2*(maxx-pre),pre=maxx; } tmpp++; // printf("%d %d\n",i,x); printf("tmp=%d\n",tmpp); if(tmpp>t) return 0; } return 1; } int main() { int ans=0; m=read(),n=read(),k=read(),t=read(); for(int i=1;i<=m;i++) a[i]=read(); a[0]=0x3f3f3f3f; for(int i=1;i<=k;i++){ l[i]=read();r[i]=read();d[i]=read(); v[l[i]].push_back(make_pair(r[i],d[i])); } int l=0,r=m; sort(a+1,a+1+m,cmp); work(a[1]); while(l<=r){ int mid=(l+r)/2; if(work(a[mid])) ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); }