http://codeforces.com/problemset/problem/1260/D
首先很明顯能夠想到二分答案,把能力值數組排個序就好。
考慮怎麼check。
設當前二分值爲w,即不能直接跨過權值>w的陷阱。
將全部的陷阱按l升序排列。能夠發現,若是兩個或多個
陷阱重疊,確定是這我的直接從這幾個陷阱最小的l走到
最大的r最優。
證實?這裏只給出兩個區間重疊的狀況。
假設兩個區間分別爲[a,b],[c,d],a<c<b<d。
想把隊伍從a帶到d,第一種的總時間爲3(d-a);若是是a->c
->a->b->d->c->d,總耗時是3(c-a)+3(d-b)-(c-b)
=3d+2c-2b-3a>3d-3a。
用雙指針模擬就好。c++
#include<bits/stdc++.h> using namespace std; #define re register int #define F(x,y,z) for(re x=y;x<=z;x++) #define FOR(x,y,z) for(re x=y;x>=z;x--) #define I inline void #define IN inline int typedef long long ll; I read(int &res){ re g=1;register char ch=getchar();res=0; while(!isdigit(ch)){ if(ch=='-')g=-1; ch=getchar(); } while(isdigit(ch)){ res=(res<<3)+(res<<1)+(ch^48); ch=getchar(); } res*=g; } int n,m,k,t,p,q,X,Y,sum,lim,a[202000]; inline bool bbb(int x,int y){ return x>y; } struct Barrier{ int l,r,w; friend bool operator < (Barrier x,Barrier y){ return x.l==y.l?x.r<y.r:x.l<y.l; } }b[202000]; IN ck(int x){ if(!x)return 1; sum=0; lim=a[x]; p=1; while(p<=k&&b[p].w<=lim)p++; if(p>k)X=sum=0; else sum=X=b[p].l-1; while(p<=k){ Y=b[p].r; q=p+1; while(q<=k&&(b[q].w<=lim||b[q].l<=Y)){ if(b[q].w>lim)Y=max(Y,b[q].r); q++; } sum+=3*(Y-X); X=Y; if(q>k)break; sum+=(b[q].l-1-X); X=b[q].l-1; p=q; } sum+=(m-X); //cout<<x<<" "<<sum<<endl; if(sum<=t)return 1; return 0; } IN divided(int x,int y){ if(x==y)return x; re mid=(x+y+1)>>1; if(ck(mid))x=mid; else y=mid-1; return divided(x,y); } int main(){ read(n);read(m);read(k);read(t);m++; F(i,1,n){ read(a[i]); } sort(a+1,a+1+n,bbb); F(i,1,k){ read(b[i].l);read(b[i].r);read(b[i].w); } sort(b+1,b+1+k); b[k+1].l=0; if(m>t){ cout<<"0"; return 0; } cout<<divided(0,n); return 0; }