zoukankan      html  css  js  c++  java
  • IOI2021集训队作业 198EC Conquer the World

    树上老鼠进洞问题。

    要求每个老鼠必须要进一个洞,洞有容量,洞可以不满。

    (nle 2.5*10^5)(sum 老鼠le10^6)


    其实和普通的老鼠进洞没有什么区别。不过加深了下对老鼠进洞的理解。

    实际上可以认为老鼠和洞没有区别,只是老鼠必须全部进洞,此时让老鼠都带上(-infty)的权即可。

    用可并堆来维护。

    在某个节点的时候,把它当做LCA统计。老鼠和洞的权值加上各自的(dep),在(LCA)处反正都要减去(2dep_{lca})所以不会因为具体位置产生权值改变。

    取出两个堆的堆顶加起来并减去(2dep_{lca}),如果小于(0)就进行配对,配对之后把反悔操作加入堆中。


    using namespace std;
    #include <bits/stdc++.h>
    #define N 250005
    #define ll long long
    #define fi first
    #define se second
    #define mp(x,y) make_pair(x,y)
    #define INF 1000000000000
    int n;
    struct EDGE{
    	int to,w;
    	EDGE *las;	
    } e[N*2];
    int ne;
    EDGE *last[N];
    void lk(int u,int v,int w){
    	e[ne]={v,w,last[u]};
    	last[u]=e+ne++;
    }
    struct Node{
    	Node *l,*r;
    	int dep;
    	pair<ll,ll> v;
    } *null;
    int cnt;
    Node *newnode(pair<ll,ll> v){
    	Node *nw=new Node;
    	*nw={null,null,0,v};
    	return nw;
    }
    Node *merge(Node *a,Node *b){
    	if (a==null) return b;
    	if (b==null) return a;
    	if (a->v>b->v) swap(a,b);
    	a->r=merge(a->r,b);
    	if (a->l->dep<a->r->dep)
    		swap(a->l,a->r);
    	a->dep=a->l->dep+1;
    	return a;
    }
    void push(Node *&t,pair<ll,ll> v){
    	Node *u=newnode(v);
    	t=merge(t,u);
    }
    void pop(Node *&t){
    	Node *u=t;
    	t=merge(u->l,u->r);
    	delete u;
    }
    Node *q0[N],*q1[N];
    ll ans;
    int a[N];
    ll dep[N];
    void dfs(int x,int fa){
    	q0[x]=q1[x]=null;
    	if (a[x]>0)
    		push(q0[x],mp(-INF+dep[x],a[x]));
    	else
    		push(q1[x],mp(dep[x],-a[x]));
    	for (EDGE *ei=last[x];ei;ei=ei->las)
    		if (ei->to!=fa){
    			dep[ei->to]=dep[x]+ei->w;
    			dfs(ei->to,x);
    			q0[x]=merge(q0[x],q0[ei->to]);
    			q1[x]=merge(q1[x],q1[ei->to]);
    		}
    	while (q0[x]!=null && q1[x]!=null && q0[x]->v.fi+q1[x]->v.fi-2*dep[x]<0){
    		pair<ll,ll> v0=q0[x]->v,v1=q1[x]->v;
    		pop(q0[x]);
    		pop(q1[x]);
    		ll tmp=min(v0.se,v1.se);
    		ans+=(v0.fi+v1.fi-2*dep[x])*tmp;
    		push(q0[x],mp(-(v0.fi+v1.fi-2*dep[x])+v0.fi,tmp));
    		push(q1[x],mp(-(v0.fi+v1.fi-2*dep[x])+v1.fi,tmp));
    		v0.se-=tmp,v1.se-=tmp;
    		if (v0.se) push(q0[x],v0);
    		if (v1.se) push(q1[x],v1);
    	}
    }
    int main(){
    //	freopen("in.txt","r",stdin);
    	scanf("%d",&n);
    	for (int i=1;i<n;++i){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		lk(u,v,w),lk(v,u,w);
    	}
    	ll sum=0;
    	for (int i=1;i<=n;++i){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		a[i]=y-x;
    		if (a[i]>0)
    			sum+=a[i];
    	}
    	null=new Node;
    	*null={null,null,0};
    	dfs(1,0);
    	ans+=sum*INF;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    高并发系统设计(二十):分布式架构如何跟踪排查慢请求问题?
    Git将多个commit合并成一个commit
    高并发系统设计(十九)【注册中心】:微服务架构结合RPC框架如何做到分布式系统寻址?
    高并发系统设计(十八):【RPC框架】10万QPS下如何实现毫秒级的服务调用?
    AfxSocketInit()
    TEXTMETRIC 结构详解
    OnInitialUpdate函数
    SetForegroundWindow
    GetSafeHwnd()函数
    MFC之CCommandLineInfo
  • 原文地址:https://www.cnblogs.com/jz-597/p/14551678.html
Copyright © 2011-2022 走看看