CF1034D Intervals of Intervals 题解
首先我们可以二分出第\(k\)条线的长度,然后统计长度大于等于这条线的线长度的总和(如果个数多了减去对应个数乘第\(k\)条线的长度即可,原因显然,在此略掉证明)
考虑转化题意,变成一条\(n\)个点,统计每一个点最后一次被哪一条线覆盖,如果说第\(i\)条线覆盖了第\(x\)条线\(l\)到\(r\)的位置,就会给\(x+1\)到\(i\)增加\(r-l+1\)的权值,然后使用颜色段均摊,可以整出总共需要加的\(O(n)\)段,考虑枚举右端点,左端点单调不降,考虑神秘差分(思路大体为大于\(x\)的位置,然后不断右移统计总个数/总长度。具体见代码,非常的easy)。
代码:
#include <bits/stdc++.h>
#define int long long
#define pii pair<pair<int,int>,int>
#define lid (id<<1)
#define rid (id<<1|1)
#define mid ((l+r)/2)
using namespace std;
const int maxn=3e5+10;
int n,k,a[maxn],b[maxn],now,ans,anss,ge,wei,l1,l2,l3,L,nowg;
int l4,l5,l[maxn<<2],r[maxn<<2],v[maxn<<2],tot,tp,f[maxn],res,ll,rr;
set<pii>s;
inline void duan(int q){
auto it=s.lower_bound({{q,0},0});
if((*it).first.first==q){
return;
}
it--;
l1=(*it).first.first;
l2=q-1;
l3=q;
l4=(*it).first.second;
l5=(*it).second;
s.erase(it);
s.insert({{l1,l2},l5});
s.insert({{l3,l4},l5});
return;
}
void init(){
s.insert({{1,rr},0});
s.insert({{rr+1,rr+1},0});
for(int i=1;i<=n;i++){
duan(a[i]);
duan(b[i]+1);
auto it=s.lower_bound({{a[i],0},0});
while((*it).first.first<=b[i]){
tot++;
l[tot]=(*it).second+1;
r[tot]=i;
v[tot]=(*it).first.second-(*it).first.first+1;
s.erase(it);
it=s.lower_bound({{a[i],0},0});
}
s.insert({{a[i],b[i]},i});
}
}
inline int check(int jie){
for(int i=1;i<=n;i++){
f[i]=0;
}
ge=0;
L=0;
tp=0;
for(int i=1;i<=n;i++){
while(r[tp+1]==i){
tp++;
f[max(l[tp],L)]+=v[tp];
f[r[tp]+1]-=v[tp];
}
while(L+1<=i&&f[L+1]+f[L]>=jie){
f[L+1]+=f[L];
L++;
}
ge+=L;
}
return ge;
}
int get_ans(int jie){
for(int i=1;i<=n;i++){
f[i]=0;
}
L=0;
tp=0;
ans=0;
res=0;
for(int i=1;i<=n;i++){
while(r[tp+1]==i){
tp++;
if(l[tp]<=L){
res+=(L-l[tp]+1)*v[tp];
}
f[max(l[tp],L)]+=v[tp];
f[r[tp]+1]-=v[tp];
}
while(L+1<=i&&f[L+1]+f[L]>=jie){
f[L+1]+=f[L];
res+=f[L+1];
L++;
}
ans+=res;
}
return ans;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
b[i]--;
rr=max(rr,b[i]);
}
init();
ll=1;
while(ll<=rr){
int midd=(ll+rr)/2;
if(check(midd)>=k){
now=midd;
ll=midd+1;
}
else{
rr=midd-1;
}
}
cout<<get_ans(now)-(check(now)-k)*now;
return 0;
}
浙公网安备 33010602011771号