zoukankan      html  css  js  c++  java
  • BZOJ 3672: [Noi2014]购票

    斜率优化+点分治(CDQ?)

    首先处理一个分治中心到这一块子树的最高点(子树的根)的链上的DP值

    优先分治处理包含根的子树,然后再处理其他子树

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    long long root,Num,N,st,Top,cnt,last[1000005],sz[1000005],F_[1000005],p[1000005],q[1000005],lim[1000005],Dep[1000005],Fa[1000005],vis[1000005];
    long long F[1000005];
    struct node1{
    	long long k,b;
    }stack[1000005];
    struct node2{
    	long long x,val;
    }E[1000005];
    struct node{
    	int to,next;
    	long long val;
    }e[1000005];
    void add(int a,int b,long long c){
    	e[++cnt].to=b;
    	e[cnt].next=last[a];
    	e[cnt].val=c;
    	last[a]=cnt;
    }
    void dfs(int x,int fa,long long dep){
    	sz[x]=1;
    	Dep[x]=dep;
    	for (int i=last[x]; i; i=e[i].next){
    		int V=e[i].to;
    		if (V==fa) continue;
    		dfs(V,x,dep+e[i].val);
    		sz[x]+=sz[V];
    	}
    }
    void find_root(int x,int fa){
    	sz[x]=1,F_[x]=0;
    	for (int i=last[x]; i; i=e[i].next){
    		int V=e[i].to;
    		if (vis[V] || V==fa) continue;
    		find_root(V,x);
    		sz[x]+=sz[V];
    		F_[x]=max(F_[x],sz[V]);
    	}
    	F_[x]=max(F_[x],N-sz[x]);
    	if (F_[x]<F_[root]) root=x;
    }
    void Pre(int x,int fa){
    	E[++Num]=(node2){x,Dep[x]-lim[x]};
    	for (int i=last[x]; i; i=e[i].next){
    		int V=e[i].to;
    		if (vis[V] || V==fa) continue;
    		Pre(V,x);
    	}
    }
    bool cmp(node2 a,node2 b){
    	return a.val>b.val;
    }
    double check(node1 a,node1 b){
    	return ((double)a.b-b.b)/(b.k-a.k);
    }
    void insert(int x){
    	node1 line=(node1){-Dep[x],F[x]};
    	while (Top>1 && check(line,stack[Top])>=check(stack[Top],stack[Top-1])) Top--;
    	stack[++Top]=line;
    }
    void Divide(int x,int S){
    	if (S<=1) return;
    	root=0,N=S;
    	find_root(x,0);
    	int Root=root;
    	for (int i=last[Fa[root]]; i; i=e[i].next){
    		int V=e[i].to;
    		if (vis[V]) continue;
    		if (V==Root) {
    			vis[Root]=1;
    			Divide(x,sz[x]-sz[Root]);
    			break;
    		}
    	}
    	for (int now=Fa[Root]; now!=Fa[x]; now=Fa[now])
    		if (Dep[now]>=Dep[Root]-lim[Root]) F[Root]=min(F[Root],F[now]+1ll*(Dep[Root]-Dep[now])*p[Root]+q[Root]);
    	Num=0;
    	for (int i=last[Root]; i; i=e[i].next){
    		int V=e[i].to;
    		if (vis[V] || V==Fa[Root]) continue;
    		Pre(V,Root);
    	}
    	sort(E+1,E+Num+1,cmp);
    	Top=0,st=Root;
    	for (int i=1; i<=Num; i++){
    		int X=E[i].x;
    		while (st!=Fa[x] && Dep[st]>=Dep[X]-lim[X]){
    			insert(st);
    			st=Fa[st];
    		}
    		if (Top){
    			int L=1,R=Top;
    			while (L<R){
    				int mid=(L+R)>>1;
    				double l,r;
    				if (mid==Top) l=-1ll<<60;
    				else l=check(stack[mid],stack[mid+1]);
    				if (mid==1)  r=1ll<<60;
    				else r=check(stack[mid],stack[mid-1]);
    				if (p[X]>=l && p[X]<=r){
    					L=mid;
    					break;
    				}
    				else if (p[X]<l) L=mid+1;
    				else R=mid-1;
    			}
    			F[X]=min(F[X],1ll*Dep[X]*p[X]+q[X]+stack[L].b+stack[L].k*p[X]);
    		}
    	}
    	for (int i=last[Root]; i; i=e[i].next){
    		int V=e[i].to;
    		if (vis[V] || V==Fa[Root]) continue;
    		Divide(V,sz[V]);
    	}
    }
    int main(){
     	int n,t;
    	scanf("%d%d",&n,&t);
    	for (int i=2; i<=n; i++){
    		long long Len;
    		scanf("%lld%lld%lld%lld%lld",&Fa[i],&Len,&p[i],&q[i],&lim[i]);
    		add(Fa[i],i,Len);
    		add(i,Fa[i],Len);
    	}
    	dfs(1,0,0);
    	for (int i=2; i<=n; i++) F[i]=1ll<<60;
    	F_[0]=1e9;
    	Divide(1,n);
    	for (int i=2; i<=n; i++)
    		printf("%lld
    ",F[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    Spring——注解代替XML配置文件,Spring与JUnit整合
    Spring——基本概念(IOC,DI思想),Spring配置文件(XML),属性注入,Spring与Web项目结合
    Struts——自定义拦截器
    Struts——OGNL表达式与Struts2结合
    Struts2——结果跳转方式配置(重定向,转发<默认>,重定向到方法,重定向到转发),获取servlet的内些API(request,servletcontext...),获取参数
    Struts2——基本使用与配置文件
    基于中间件的RBAC权限控制
    Django
    Django
    Django 中 admin 的执行流程
  • 原文地址:https://www.cnblogs.com/silenty/p/9801021.html
Copyright © 2011-2022 走看看