[CF1523G] Try Booking

\(\text{Problem}:\)Try Booking

\(\text{Solution}:\)

首先不难发现对于所有 \(x\),租借出公寓的总数是 \(O(n\ln n)\) 级别的。

对于某个固定的 \(x\),按照以下方式求出答案:在 \([1,n]\) 中找到编号最小的区间 \([l,r]\),然后递归 \([1,l-1]\)\([r+1,n]\)。这个问题只需维护一棵动态开点线段树即可解决。

现在考虑倒序求出每个 \(x\) 的答案,每层需要支持插入若干个新的区间。注意到这等于对所有 \(i\geq r\) 进行了单点修改,故我们可以用树状数组套线段树去维护。

总时间复杂度 \(O((n\ln n+m)\log^{2}n)\)

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=100010;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,m;
struct Node { int l,r,id; }g[N]; vector<Node> q[N];
struct Tree { int lc,rc,mi; }D[N*256]; int root[N],cnt;
void UpDate(int &x,int l,int r,int pos,int k)
{
	if(!x) x=++cnt, D[x].mi=k;
	else D[x].mi=min(D[x].mi,k);
	if(l==r) return;
	int mid=(l+r)/2;
	if(pos<=mid) UpDate(D[x].lc,l,mid,pos,k);
	else UpDate(D[x].rc,mid+1,r,pos,k);
}
int Query(int x,int l,int r,int u,int v)
{
	if(!x||l>r) return 1e9;
	if(l>=u&&r<=v) return D[x].mi;
	int mid=(l+r)/2,tt=1e9;
	if(u<=mid) tt=min(tt,Query(D[x].lc,l,mid,u,v));
	if(v>mid) tt=min(tt,Query(D[x].rc,mid+1,r,u,v));
	return tt;
}
struct BIT
{
	int c[N];
	inline int lowbit(int x) { return x&(-x); }
	inline void Add(int x,int l,int p) { for(;x<=n;x+=lowbit(x)) UpDate(root[x],1,n,l,p); }
	inline int Ask(int l,int r) { int tt=1e9; for(;r>=l;r-=lowbit(r)) tt=min(tt,Query(root[r],1,n,l,r)); return tt; }
}A;
int Getans(int l,int r)
{
	if(l>r) return 0;
	int gt=A.Ask(l,r);
	if(gt==1e9) return 0;
	return g[gt].r-g[gt].l+1+Getans(l,g[gt].l-1)+Getans(g[gt].r+1,r);
}
signed main()
{
	n=read(), m=read();
	for(ri int i=1;i<=m;i++)
	{
		int l,r;
		l=read(), r=read();
		q[r-l+1].eb((Node){l,r,i});
		g[i]=(Node){l,r,i};
	}
	vi ot;
	for(ri int i=n;i;i--)
	{
		for(auto j:q[i]) A.Add(j.r,j.l,j.id);
		ot.eb(Getans(1,n));
	}
	reverse(ot.begin(),ot.end());
	for(auto i:ot) printf("%d\n",i);
	return 0;
}
posted @ 2021-10-27 08:44  zkdxl  阅读(77)  评论(1编辑  收藏  举报