显然答案与杆的顺序无关(按每个高度考虑)。
从高到低考虑杆,设此时的状态为\(S?\),\(S[i]?\)是高度\(i?\)的帆的数目,初始全为\(0?\),当前杆的高度为\(h?\),杆上需要放置的帆的数目为\(k?\),贪心地,假设两个高度的同等宜选,优先选择更高的;帆尽量放置在\(S[i]=0(i\le h)?\)的高度上,若还有剩余,设剩下\(t(t\le k)?\)个,则放置在除去以选择的高度以外,\(S[i](i\le h)?\)前\(t?\)小的位置。
整理一下,每次选出\(S[1\cdots h]\)中前\(k\)小的(相同大小选下标较大的)高度放置帆。
{5,3} 0 0 1 1 1 +0
{4,3} 1 1 2 1 1 +1
{4,1} 1 2 2 1 1 +1
{3,2} 2 2 3 1 1 +3
{3,2} 3 3 3 1 1 +4
{2,1} 3 4 3 1 1 +3
但是此时\(S?\)似乎不好维护。。考虑将过程倒过来,从低到高考虑杆,(\(S?\)一开始为空集,其余定义相同),假设两个高度同等宜选,优先选择更低的,其余大致相同。即每次选出\(S[1\cdots h]?\)中前\(k?\)小的(相同大小选下标较小的)高度放置帆。
{2,1} 1 0 +0
{3,2} 1 1 1 +0
{3,2} 2 2 1 +2
{4,1} 2 2 1 1 +0
{4,3} 3 2 2 2 +4
{5,3} 3 3 3 2 1 +4
这样把\(B\)看成动态插入(长度变化时补0),每次查询全局前\(k\)小然后整体加一即可。(省去了下标范围的约束)。进一步可发现,连下标都不用维护了
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node {
int siz,fa,ch[2];
int sum,val,add;
} t[N];
int root,tot;
#define ls t[x].ch[0]
#define rs t[x].ch[1]
void upd(int x) {
t[x].siz=t[ls].siz+t[rs].siz+1;
t[x].sum=t[ls].sum+t[rs].sum+t[x].val;
}
void add(int x,int w) {if(x) t[x].add+=w,t[x].val+=w,t[x].sum+=t[x].siz*w;}
void psd(int x) {if(t[x].add) add(ls,t[x].add),add(rs,t[x].add),t[x].add=0;}
bool get(int x) {return t[t[x].fa].ch[1]==x;}
void rtt(int x) {
int y=t[x].fa,k=get(x); if(t[y].fa) t[t[y].fa].ch[get(y)]=x;
t[x].fa=t[y].fa;t[t[x].ch[k^1]=t[t[y].ch[k]=t[x].ch[k^1]].fa=y].fa=x;upd(y);
}
void spl(int x,int d) {
for(; t[x].fa!=d; rtt(x)) if(t[t[x].fa].fa!=d)
rtt(get(x)^get(t[x].fa)?x:t[x].fa);
upd(x); if(d==0) root=x;
}
void insert(int w) {
int x=root,d=0;
while(x) x=t[d=x].ch[t[x].val<w];
x=++tot,t[x]=(node){1,d,{0,0},w,w,0};
if(d) t[d].ch[t[d].val<w]=x; spl(x,0);
}
int kth(int k) {
int x=root;
while("orz") {
psd(x);
if(k>t[ls].siz+1) k-=t[ls].siz+1,x=rs;
else if(k==t[ls].siz+1) return x;
else x=ls;
}
}
void show(int x) {
if(!x) return;
show(t[x].ch[0]),printf("%d ",t[x].val),show(t[x].ch[1]);
}
void write(int x) {show(x); putchar('\n');}
int n;
long long ans;
pair<int,int> a[N];
int main() {
scanf("%d",&n);
for(int i=1; i<=n; ++i) scanf("%d%d",&a[i].first,&a[i].second);
a[0]=make_pair(0,0),sort(a+1,a+n+1);
insert(-1e9),insert(1e9);
for(int i=1; i<=n; ++i) {
for(int t=a[i].first-a[i-1].first; t--;) insert(0);
int x=kth(1),y=kth(a[i].second+2);
spl(x,0),spl(y,x);
/*还有点东西没写完tat*/
}
printf("%lld\n",ans);
return 0;
}