噁心題,不想說話。
二分,倒過來搞;
\(h[i]+m*a[i]-num*p<=x\)可推出\(h[i]<=x+num*p-m*a[i]\)
題目變爲:
每根竹子原長度爲\(x\),天天減小\(a[i]\)長度,每次能夠添加\(p\)長度,現長度不得小於0,
貪心的選擇,儘量不添加長度,每次給最近長度就會小於0的竹子添加長度,若是最後仍小於\(h[i]\),就繼續入隊。c++
#include<bits/stdc++.h> #define lc x<<1 #define rc x<<1|1 using namespace std; const int N=1e5+7; int n,q,t,t1,t2,lf,rg,LCA,LCA2,cnt=0,num=0,ansl,ansr,d[N],dfn[N],rev[N],head[N],Min[N<<2],Max[N<<2],f[N][21]; struct edge{int nxt,to;}e[N]; inline void add(int u,int v){e[++cnt].nxt=head[u],e[cnt].to=v,head[u]=cnt;} inline int read(){ int T=0,F=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();} while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar(); return F*T; } void dfs(int x,int fa){ d[x]=d[fa]+1,f[x][0]=fa,dfn[x]=++num,rev[num]=x; for(int i=1;i<=18;++i) f[x][i]=f[f[x][i-1]][i-1]; for(int i=head[x];i;i=e[i].nxt) dfs(e[i].to,x); } void build(int l,int r,int x){ if(l==r){Min[x]=Max[x]=dfn[l]; return;} int mid=l+r>>1; build(l,mid,lc),build(mid+1,r,rc); Max[x]=max(Max[lc],Max[rc]),Min[x]=min(Min[lc],Min[rc]); } int query(int l,int r,int p,int q,int x){ if(p>q) return n+1; if(p<=l&&r<=q) return Min[x]; int mid=l+r>>1,ans=n+1; if(p<=mid) ans=min(ans,query(l,mid,p,q,lc)); if(q>mid) ans=min(ans,query(mid+1,r,p,q,rc)); return ans; } int query2(int l,int r,int p,int q,int x){ if(p>q) return 0; if(p<=l&&r<=q) return Max[x]; int mid=l+r>>1,ans=0; if(p<=mid) ans=max(ans,query2(l,mid,p,q,lc)); if(q>mid) ans=max(ans,query2(mid+1,r,p,q,rc)); return ans; } int lca(int x,int y){ if(d[x]<d[y]) swap(x,y); for(int i=18;i>=0;--i) if(d[x]>=d[y]+(1<<i)) x=f[x][i]; if(x==y) return x; for(int i=18;i>=0;--i) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } int main(){ n=read(),q=read(); for(int i=2;i<=n;++i) t=read(),add(t,i); d[0]=-1,dfs(1,0),build(1,n,1); for(int i=1;i<=q;++i){ t1=read(),t2=read(),lf=rev[query(1,n,t1,t2,1)],rg=rev[query2(1,n,t1,t2,1)]; ansl=rev[min(query(1,n,t1,lf-1,1),query(1,n,lf+1,t2,1))]; ansr=rev[max(query2(1,n,t1,rg-1,1),query2(1,n,rg+1,t2,1))]; LCA=lca(ansl,rg),LCA2=lca(lf,ansr); if(d[LCA]>d[LCA2]) printf("%d %d\n",lf,d[LCA]); else printf("%d %d\n",rg,d[LCA2]); } return 0; }