zoukankan      html  css  js  c++  java
  • 【洛谷P3992】开车

    题目

    题目链接:https://www.luogu.com.cn/problem/P3992
    \(n\) 辆车,分别在 \(a_1, a_2, \ldots , a_n\) 位置和 \(n\) 个加油站,分别在 \(b_1, b_2, \ldots ,b_n\) 位置。
    每个加油站只能支持一辆车的加油,所以你要把这些车开到不同的加油站加油。一个车从 \(x\) 位置开到 \(y\) 位置的代价为 \(|x-y|\),问如何安排车辆,使得代价之和最小。
    同时你有 \(q\) 个操作,每次操作会修改第 \(i\) 辆车的位置到 \(x\),你要回答每次修改操作之后最优安排方案的总代价。
    \(n,q\leq 5\times 10^4\)\(0\leq a_i,b_i\leq 10^9\)

    思路

    很显然最优的匹配方式是将 \(a\)\(b\) 分别排序后一一对应。但是这样并不好搞修改操作,因为一次修改可能会更改很多的匹配,而更改匹配后每一个位置的差的绝对值只能分开来考虑。
    把初始和以后修改到的所有位置都存下来离散化,记 \(w_i\) 表示离散化后位置 \(i\) 与位置 \(i+1\) 之间的实际距离,\(s_i\) 表示位置 \(i\) 前面车辆的数量减去加油站的数量。那么答案其实就是

    \[\sum^{cnt}_{i=1}|s_i|\times w_i \]

    因为在最优匹配方式下,前 \(i\) 个位置的车和加油站一定是两两匹配,多出来的 \(|s_i|\) 个车(或者加油站)只能往后匹配,那么位置 \(i\) 与位置 \(i+1\) 这一条边的贡献就是 \(|s_i|\)
    这个东西虽然也有绝对值,但是观察到一次修改相当于把一段区间的 \(s\) 全部 \(+1\)\(-1\),这个东西明显可做多了。
    考虑分块,对每一个块的 \(s\) 新开一个数组 \(t\) 排序,修改的时候整块直接打 tag,零散的块暴力修改 \(a\) 的值,然后把块重构。
    对于一次询问,枚举每一个块,可以在 \(t\) 上二分找到一个邻界点 \(p\),这个块中在 \(p\) 前面的所有元素都满足 \(t_i+\) 这个块的 tag \(<0\)\(p\) 后面的所有元素都满足 \(t_i+\) 这个块的 tag \(\geq 0\)。那么就可以把绝对值拆开了。
    每一个块暴力重构的时候顺便求出前缀的 \(w\) 之和,以及 \(|t_i|\times w\) 之和即可。
    时间复杂度 \(O(n\sqrt{n}\log n)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=150010,B=350;
    int n,m,lim,Q,X[N],Y[N],a[N],b[N],c[N],w[N],bel[N],L[N/B+10],R[N/B+10],add[N/B+10];
    ll res[N],sum[N];
    
    struct node
    {
    	int x,y;
    }qry[N];
    
    bool cmp(int x,int y)
    {
    	return a[x]<a[y];
    }
    
    void build(int i)
    {
    	sort(b+L[i],b+R[i]+1,cmp);
    	res[L[i]]=1LL*a[b[L[i]]]*w[b[L[i]]];
    	sum[L[i]]=w[b[L[i]]];
    	for (int j=L[i]+1;j<=R[i];j++)
    	{
    		res[j]=res[j-1]+1LL*a[b[j]]*w[b[j]];
    		sum[j]=sum[j-1]+w[b[j]];
    	}
    }
    
    void update(int l,int r,int v)
    {
    	int bl=bel[l],br=bel[r];
    	if (bl==br)
    	{
    		for (int i=l;i<=r;i++) a[i]+=v;
    		build(bl); return;
    	}
    	for (int i=bl+1;i<br;i++) add[i]+=v;
    	for (int i=l;i<=R[bl];i++) a[i]+=v;
    	for (int i=r;i>=L[br];i--) a[i]+=v;
    	build(bl); build(br);
    }
    
    void query()
    {
    	ll ans=0;
    	for (int i=1;i<=lim;i++)
    	{
    		int l=L[i],r=R[i],mid;
    		while (l<=r)
    		{
    			mid=(l+r)>>1;
    			if (a[b[mid]]+add[i]>=0) r=mid-1;
    				else l=mid+1;
    		}
    		int p=r+1;
    		if (p==L[i])
    			ans+=res[R[i]]+sum[R[i]]*add[i];
    		else
    		{
    			ans+=res[R[i]]-res[p-1]+(sum[R[i]]-sum[p-1])*add[i];
    			ans-=res[p-1]+sum[p-1]*add[i];
    		}
    	}
    	printf("%lld\n",ans);
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&X[i]),c[++m]=X[i];
    	for (int i=1;i<=n;i++)
    		scanf("%d",&Y[i]),c[++m]=Y[i];
    	scanf("%d",&Q);
    	for (int i=1;i<=Q;i++)
    	{
    		scanf("%d%d",&qry[i].x,&qry[i].y);
    		c[++m]=qry[i].y;
    	}
    	sort(c+1,c+1+m);
    	m=unique(c+1,c+1+m)-c-1;
    	for (int i=1;i<=m;i++) w[i]=c[i+1]-c[i];
    	for (int i=1;i<=n;i++)
    	{
    		X[i]=lower_bound(c+1,c+1+m,X[i])-c;
    		Y[i]=lower_bound(c+1,c+1+m,Y[i])-c;
    		a[X[i]]++; a[Y[i]]--;
    	}
    	n=m; lim=(n-1)/B+1;
    	for (int i=1;i<=n;i++)
    		a[i]+=a[i-1],b[i]=i;
    	for (int i=1;i<=lim;i++)
    	{
    		L[i]=R[i-1]+1; R[i]=min(n,i*B);
    		for (int j=L[i];j<=R[i];j++) bel[j]=i;
    		build(i);
    	}
    	query();
    	for (int i=1;i<=Q;i++)
    	{
    		qry[i].y=lower_bound(c+1,c+1+m,qry[i].y)-c;
    		if (X[qry[i].x]<qry[i].y) update(X[qry[i].x],qry[i].y-1,-1);
    		if (X[qry[i].x]>qry[i].y) update(qry[i].y,X[qry[i].x]-1,1);
    		X[qry[i].x]=qry[i].y;
    		query();
    	}
    	return 0;
    }
    
  • 相关阅读:
    Atitit 趋势管理之道 attilax著
    Atitit 循环处理的新特性 for...else...
    Atitit 2017年的技术趋势与未来的大技术趋势
    atitit 用什么样的维度看问题.docx 如何了解 看待xxx
    atitit prj mnrs 项目中的几种经理角色.docx
    Atitit IT办公场所以及度假村以及网点以及租房点建设之道 attilax总结
    Atitit 工具选型的因素与方法 attilax总结
    Atitit.团队文化建设影响组织的的一些原理 法则 定理 效应 p826.v4
    Atiitt 管理方面的误区总结 attilax总结
    Atitit 未来趋势把控的书籍 attilax总结 v3
  • 原文地址:https://www.cnblogs.com/stoorz/p/15567398.html
Copyright © 2011-2022 走看看