首页 > 其他分享 >CF1034D Intervals of Intervals

CF1034D Intervals of Intervals

时间:2022-11-21 02:44:06浏览次数:38  
标签:insert int mid len pb Intervals CF1034D define

题意:给定 \(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;
}

标签:insert,int,mid,len,pb,Intervals,CF1034D,define
From: https://www.cnblogs.com/syzf2222/p/16910204.html

相关文章

  • CF1034D
    \(3500\)。根本想不到这种思路。先考虑这么一个问题:给定\(n\)个区间\([a_i,b_i)\)。\(q\)次询问,每次查询\((\cup_{l\lei\ler}[a_i,b_i))\cap\mathbbZ\)的元......
  • 56. Merge Intervals
    Givenanarray of intervals where intervals[i]=[starti,endi],mergealloverlappingintervals,andreturn anarrayofthenon-overlappingintervalstha......
  • LeetCode 435. Non-overlapping Intervals
    贪心按照有边界排序,只有先选择了右边边界小的,才可以放下更多的区间classSolution{public:interaseOverlapIntervals(vector<vector<int>>&intervals){......
  • 435.non-overlapping-intervals 无重叠区间
    问题描述435.无重叠区间解题思路本题和452.用最少数量的箭引爆气球可以说解题思路一模一样,区间数减去452.用最少数量的箭引爆气球就可以说是本题要求的答案,但是要注意的......
  • LeetCode_Array_56. Merge Intervals (C++)
    目录​​1,题目描述​​​​2,解题思路​​​​3,代码【C++】​​​​4,运行比较​​1,题目描述Givenacollectionofintervals,mergealloverlappingintervals.Example1:I......
  • Leetcode第915题:分割数组(Partrition Array Into Disjoint Intervals)
    解题思路最终的是将一个数组分为两个数组:左数组和右数组。这两个数组满足:左数组的最大值小于右数组的任何值。需要一个变量left_max来记录左数组的最大值。左数组长度......
  • POJ 1201 Intervals 差分约束
    ​​http://poj.org/problem?id=1201​​TLE了很久,因为用了cin.....思路和其他差分约束差不多,​​http://www.cppblog.com/menjitianya/archive/2015/11/19/212292.html​​......