[CTSC2016]时空旅行(线段树+凸包)
Posted HocRiser
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CTSC2016]时空旅行(线段树+凸包)相关的知识,希望对你有一定的参考价值。
应该是比较套路的,但是要A掉仍然不容易。
下面理一下思路,思路清楚了也就不难写出来了。
0.显然y,z坐标是搞笑的,忽略即可。
1.如果x不变,那么直接set即可解决。
2.考虑一个空间和询问x0,通过化式子发现实际上就是:把每个星球看成一个一次函数,其实是在询问这个空间内的所有一次函数在x0处的最小值。
3.这个显然是一个凸包,所以我们需要对每个空间维护一个凸包,由空间整体呈树状,可以想到用DFS序+线段树维护区间。
4.预处理出每个星球的存在范围,在线段树上永久化标记。查询时依次递归求最小值。
5.关于线段树上如何存凸包,可以先扫一遍预留出空间,也可以直接像http://www.cnblogs.com/HocRiser/p/8549456.html一样用vector存,后者可能会慢一点,开了读入外挂就过了。
1 #include<cstdio> 2 #include<vector> 3 #include<algorithm> 4 #define ls (x<<1) 5 #define rs (ls|1) 6 #define lson ls,L,mid 7 #define rson rs,mid+1,R 8 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 9 typedef long long ll; 10 using namespace std; 11 12 const int N=500010; 13 const ll inf=1000000000000000000ll; 14 int n,m,cnt,x,y,c,tim,op,fr,d,id[N],L[N],R[N],X[N],K[N]; 15 int h[N],nxt[N],pos[N],to[N],st[N<<2],ed[N<<2],q[N]; 16 ll a[N],b[N],ans[N]; 17 vector<int>T[N<<2],V[N]; 18 19 ll rd(){ 20 ll x=0; bool t=0; char ch=getchar(); 21 while (ch<\'0\' || ch>\'9\') t|=(ch==\'-\'),ch=getchar(); 22 while (ch>=\'0\' && ch<=\'9\') x=x*10+ch-\'0\',ch=getchar(); 23 if (t) return -x; else return x; 24 } 25 26 bool cmp0(int x,int y){ return L[x]<L[y]; } 27 bool cmp1(int x,int y){ return a[x]>a[y] || (a[x]==a[y] && b[x]>b[y]); } 28 bool cmp2(int a,int b){ return X[a]<X[b]; } 29 bool Cmp(int x,int y,int z){ return ((b[y]-b[x])*(a[y]-a[z])>=(b[z]-b[y])*(a[x]-a[y])); } 30 31 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } 32 33 void dfs(int x){ L[x]=++tim; for (int i=h[x]; i; i=nxt[i]) dfs(to[i]); R[x]=tim; } 34 35 void build(int x,int L,int R){ 36 ed[x]=-1; 37 if (L==R) { pos[L]=x; return; } 38 int mid=(L+R)>>1; build(lson); build(rson); 39 } 40 41 void ins(int x,int L,int R,int l,int r,int k){ 42 if (L==l && r==R){ 43 int &j=ed[x]; 44 for (; st[x]<j && Cmp(T[x][j-1],T[x][j],k); j--,T[x].pop_back()); 45 j++; T[x].push_back(k); 46 return; 47 } 48 int mid=(L+R)>>1; 49 if (r<=mid) ins(lson,l,r,k); 50 else if (l>mid) ins(rson,l,r,k); 51 else ins(lson,l,mid,k),ins(rson,mid+1,r,k); 52 } 53 54 ll que(int k,int x){ 55 ll ans=inf; 56 for (int i=pos[k]; i; i>>=1){ 57 int &j=st[i]; 58 for (; j<ed[i] && (a[T[i][j]]-a[T[i][j+1]])*x>=b[T[i][j+1]]-b[T[i][j]]; j++); 59 if (j<=ed[i]) ans=min(ans,a[T[i][j]]*x+b[T[i][j]]); 60 } 61 return ans; 62 } 63 64 int main(){ 65 freopen("travel.in","r",stdin); 66 freopen("travel.out","w",stdout); 67 n=rd(); m=rd(); b[1]=rd(); id[1]=1; 68 rep(i,2,n){ 69 op=rd(); fr=rd()+1; d=rd()+1; add(fr,i); 70 if (op) V[d].push_back(i); 71 else id[d]=i,x=rd(),rd(),rd(),c=rd(),a[d]=-2ll*x,b[d]=1ll*x*x+c; 72 } 73 dfs(1); build(1,1,n); 74 rep(i,1,n) q[i]=i; sort(q+1,q+n+1,cmp1); 75 rep(l,1,n) if (id[q[l]]){ 76 int i=q[l]; 77 sort(V[i].begin(),V[i].end(),cmp0); int k=L[id[i]]; 78 for (vector<int>::iterator it=V[i].begin(); it!=V[i].end(); k=R[*it]+1,it++) 79 if (k<L[*it]) ins(1,1,n,k,L[*it]-1,i); 80 if (k<=R[id[i]]) ins(1,1,n,k,R[id[i]],i); 81 } 82 rep(i,1,m) q[i]=i,x=rd(),y=rd(),K[i]=L[x+1],X[i]=y; 83 sort(q+1,q+m+1,cmp2); 84 rep(i,1,m) ans[q[i]]=que(K[q[i]],X[q[i]])+1ll*X[q[i]]*X[q[i]]; 85 rep(i,1,m) printf("%lld\\n",ans[i]); 86 return 0; 87 }
以上是关于[CTSC2016]时空旅行(线段树+凸包)的主要内容,如果未能解决你的问题,请参考以下文章