题意:给定 \(N\) 条线段,定义一个区间的价值为区间线段并的长度,求前 \(K\) 大区间价值和。

题解:首先考虑一个简化版本,求区间线段并。

扫描线,维护每个左端点的答案。对于每个位置维护最后一次包含它的线段,把相邻相同的位置合并,用 \(\texttt{set}\) 维护这些连续段,复杂度是均摊的。

回到原题,考虑二分出 \(K\) 大值。令 \(L_i\) 表示以 \(i\) 为右端点时区间并 \(<M\) 的左端点,显然 \(L_i\) 单调不降。双指针的同时也可以维护出答案,详见代码。

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
const int mod=1e9+7;
const int inf=1e9;
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define lll __int128
#define fi first
#define se second
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
struct itv{
	int l,r,tg;
	bool operator<(const itv &x)const{
		return x.l^l?l<x.l:r<x.r;
	}
};set<itv>S;
inline void split(int p){
	if(!p)return;
	auto it=--S.lower_bound({p+1,0,0});
	if(it->r==p)return;
	S.insert({it->l,p,it->tg});
	S.insert({p+1,it->r,it->tg});
	S.erase(it);
}
int n,m;lll sum,cnt;
vector<pii>laz[maxn],buc[maxn];
inline bool chk(int mid){
	sum=cnt=0;ll cs=0,cur=0;
	for(int l=1,r=1;r<=n;r++){
		for(auto x:laz[r])if(x.fi<=l)
			cur+=x.se,cs+=1ll*x.se*(l-x.fi);
		while(cur>=mid){
			cs+=cur,++l;
			for(auto x:buc[l])
				if(x.fi<=r)cur+=x.se;
		}sum+=cs,cnt+=l-1;
	}return cnt>=m;
}
int main(){
	n=read(),m=read();
	S.insert({1,inf,0});
	for(int i=1,l,r;i<=n;i++){
		l=read(),r=read()-1;
		split(l-1),split(r);
		while(1){
			auto it=S.lower_bound({l,0,0});
			if(it==S.end()||it->l>r)break;
			int las=it->tg,len=it->r-it->l+1;
			laz[i].pb({las+1,len});
			laz[i].pb({i+1,-len});
			buc[las+1].pb({i,len});
			buc[i+1].pb({i,-len});
			S.erase(it); 
		}S.insert({l,r,i});
	}int l=1,r=inf,kth=0;
	while(l<=r){
		int mid=(l+r)>>1;
		if(chk(mid))kth=mid,l=mid+1;
		else r=mid-1;
	}chk(kth);
	printf("%lld\n",(ll)(sum-(cnt-m)*kth));
	return 0;
}

原文地址:http://www.cnblogs.com/syzf2222/p/16910204.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性