线段树||BZOJ5194: [Usaco2018 Feb]Snow Boots||Luogu P4269 [USACO18FEB]Snow Boots G
题面:P4269 [USACO18FEB]Snow Boots G
题解:
把所有砖和靴子排序,然后依次处理每一双靴子,把深度小于等于它的砖块都扔线段树里,问题就转化成了求线段树已有的砖块中最大的砖块间距是否小于当前靴子间距。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define max(a,b) ((a)>(b)?(a):(b)) 6 using namespace std; 7 const int maxn=(1e5)+50,maxb=(1e5)+50; 8 int N,B,f1; 9 bool ans[maxb]; 10 struct P{ 11 int x,id,d; 12 }F[maxn],S[maxb]; 13 struct Tree{ 14 int l,r,h_,t_,mx; 15 }t[maxn<<2]; 16 inline bool cmp(const P&a,const P&b){return(a.x<b.x);} 17 inline void Pushup(int x){ 18 int ls=x<<1,rs=x<<1|1; 19 if(t[ls].r-t[ls].l+1==t[ls].mx)t[x].h_=t[ls].mx+t[rs].h_;else t[x].h_=t[ls].h_; 20 if(t[rs].r-t[rs].l+1==t[rs].mx)t[x].t_=t[rs].mx+t[ls].t_;else t[x].t_=t[rs].t_; 21 t[x].mx=max(t[ls].mx,t[rs].mx); 22 t[x].mx=max(t[x].mx,t[ls].t_+t[rs].h_); 23 return; 24 } 25 inline void Build(int x,int l,int r){ 26 t[x].l=l;t[x].r=r; 27 if(l==r){ 28 t[x].h_=t[x].t_=t[x].mx=1; 29 return; 30 } 31 int mid=(l+r)>>1,ls=x<<1,rs=x<<1|1; 32 Build(ls,l,mid);Build(rs,mid+1,r); 33 Pushup(x); 34 return; 35 } 36 inline void Update(int x,int q){ 37 int l=t[x].l,r=t[x].r; 38 if(l==r&&l==q){ 39 t[x].h_=t[x].t_=t[x].mx=0; 40 return; 41 } 42 int mid=(l+r)>>1,ls=x<<1,rs=x<<1|1; 43 if(q<=mid)Update(ls,q); 44 else Update(rs,q); 45 Pushup(x); 46 return; 47 } 48 int main(){ 49 scanf("%d%d",&N,&B); 50 for(int i=1;i<=N;i++){ 51 scanf("%d",&F[i].x); 52 F[i].id=i; 53 } 54 for(int i=1;i<=B;i++){ 55 scanf("%d%d",&S[i].x,&S[i].d); 56 S[i].id=i; 57 } 58 sort(F+1,F+N+1,cmp); 59 sort(S+1,S+B+1,cmp); 60 Build(1,1,N); 61 f1=0;//F是地砖,S是靴子 ;f1是地砖,f2是靴子 62 for(int f2=1;f2<=B;f2++){//依次处理每一双靴子 63 while(f1<N&&F[f1+1].x<=S[f2].x){ 64 f1++; 65 Update(1,F[f1].id); 66 } 67 if(t[1].mx<S[f2].d)ans[S[f2].id]=1; 68 } 69 for(int i=1;i<=B;i++)printf("%d\n",ans[i]); 70 return 0; 71 }
By:AlenaNuna