【CF875E】Delivery Club 二分+線段樹
阿新 • • 發佈:2017-12-31
names turn body sort mod pri esp string etc
【CF875E】Delivery Club
題意:有n個快遞需要依次接收,這n個快遞分部在x軸上,第i個快遞的位置是xi。有兩個快遞員,一開始分別在s0,s1,你可以任意安排哪個人收哪個快遞,前提是一個快遞員收快遞是另一個快遞員不能移動(也就是說他只有在收快遞時能移動),並且要保證任何時候兩人的距離不超過k。問你k最小是多少。
n<=10^5,xi<=10^9
題解:二分是顯然的。我們可以用f[i][a][b]表示收第i個快遞時,兩個快遞員一個在a,一個在b是否可行,又因為a或b一定等於i,所以我們可以省掉一維。我們還可以用線段樹再省一維。因為在收第i+1個快遞時,要麽是在i處的快遞員走到i+1,此時與i+1距離超過k的位置a都變成了不合法的,可以用線段樹區間清零搞定;要麽是在a處的快遞員走到i+1。用線段樹很容易維護這些東西。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define lson x<<1 #define rson x<<1|1 using namespace std; const int maxn=100010; int n; int v[maxn],p[maxn],rnk[maxn]; bool s[maxn<<2]; inline int Abs(const int &a) {return a>0?a:-a;} bool cmp(const int &a,const int &b) { return v[a]<v[b]; } inline void pushdown(int x) { if(!s[x]) s[lson]=s[rson]=0; } void modify(int l,int r,int x,int a) { if(l==r) { s[x]=1; return ; } pushdown(x); int mid=(l+r)>>1; if(a<=mid) modify(l,mid,lson,a); else modify(mid+1,r,rson,a); s[x]=s[lson]|s[rson]; } void updata(int l,int r,int x,int a,int b) { if(a>b) return ; if(a<=l&&r<=b) { s[x]=0; return ; } pushdown(x); int mid=(l+r)>>1; if(a<=mid) updata(l,mid,lson,a,b); if(b>mid) updata(mid+1,r,rson,a,b); s[x]=s[lson]|s[rson]; } bool check(int len) { int i,l,r,mid; s[1]=0; modify(1,n,1,rnk[1]); for(i=3;i<=n;i++) { l=1,r=rnk[i]; while(l<r) { mid=(l+r)>>1; if(v[p[mid]]<v[i]-len) l=mid+1; else r=mid; } updata(1,n,1,1,l-1); l=rnk[i],r=n; while(l<r) { mid=(l+r)>>1; if(v[p[mid]]<=v[i]+len) l=mid+1; else r=mid; } updata(1,n,1,l,n); if(Abs(v[i]-v[i-1])<=len) modify(1,n,1,rnk[i-1]); if(!s[1]) return 0; } return 1; } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘) f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+(gc^‘0‘),gc=getchar(); return ret*f; } int main() { n=rd()+2; int i,l=0,r=0,mid; for(i=1;i<=n;i++) v[i]=rd(),r=max(r,v[i]),p[i]=i; sort(p+1,p+n+1,cmp); for(i=1;i<=n;i++) rnk[p[i]]=i; v[0]=-1000000000,v[n+1]=1000000000; l=Abs(v[2]-v[1]); while(l<r) { mid=(l+r)>>1; if(check(mid)) r=mid; else l=mid+1; } printf("%d",r); return 0; }
【CF875E】Delivery Club 二分+線段樹