CF1523G Try Booking
CF1523G Try Booking
Lemma1
首先,对于强制处理 \(r-l+1\ge x\)
比较直观的做法就是按照r-l+1离线
于是问题就很轻松的转化为了
按原顺序给定m个染色操作,要求每个染色操作的区间未被染过
Lemma2
同时注意到对于所有 \(x\in[1,n]\) 合法的查询数不会超过\(\left\lfloor\dfrac{n}{x}\right\rfloor\)
所以总的合法查询数不超过\(nlnn\)
这显然是解题的一个关键所在
Solve
结合\(lemma2\)我们就可以大胆的取出合法的区间进行统计
但是还有一点问题,如何快速的找到合法的区间
如果找到合法区间,我们可以将原区间分裂为未被染色的两个区间如法炮制
于是,现在需要解决的问题就成了
在区间\([L,R]\)迅速找到一个合法的染色操作\(k_{min}\),使得\(L\le l_k\le r_k \le R\)
一个非常简单的三维偏序,考虑到在线做法,可以用树套树维护
时间复杂度\(O(Mlog^2_2 N+Nln Nlog^2_2N)\)
空间复杂度\(O(Mlog_2^2N)\)
这时回顾一下数据范围\(n\le 5e4\)而非传统的\(1e5\),仿佛在暗示着什么
代码环节
#include<bits/stdc++.h>
using namespace std;
#define Mod(x) (x>=P)&&(x-=P)
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
#define erep(i,a) for(int i=hd[a];i;i=nxt[i])
typedef long long ll;
void Max(int &x,int y){(x<y)&&(x=y);}
void Min(int &x,int y){(x>y)&&(x=y);}
bool vio;
char IO;
int rd(int res=0){
bool f=0;
while(IO=getchar(),IO<48||IO>57)
f=IO=='-';
do res=(res<<1)+(res<<3)+(IO^48);
while(IO=getchar(),isdigit(IO));
return f?-res:res;
}
const int M=1e5+10;
vector<int>g[M];
int Mn[M<<8],ls[M<<8],rs[M<<8];
int l[M],r[M],ans[M],rt[M],n,m;
void upd(int &cur,int x,int k,int L=1,int R=n,int p=1){
static int tot;
if(!cur)Mn[cur=++tot]=m+1;
Min(Mn[cur],k);
if(L==R)return ;
int mid=(L+R)>>1;
if(x<=mid)upd(ls[cur],x,k,L,mid,p<<1);
else upd(rs[cur],x,k,mid+1,R,p<<1|1);
}
int qry(int cur,int x,int L=1,int R=n,int p=1){
if(L==R)return Mn[cur];
int mid=(L+R)>>1;
if(x>mid)return qry(rs[cur],x,mid+1,R,p<<1|1);
return min(qry(ls[cur],x,L,mid,p<<1),Mn[rs[cur]]);
}
void Add(int l,int r,int id){
while(r<M)upd(rt[r],l,id),r+=r&-r;
}
int calc(int l,int r){
int res=m+1;
while(r)Min(res,qry(rt[r],l)),r-=r&-r;
return res;
}
int solve(int L,int R){
if(L>R)return 0;
int t=calc(L,R);
if(t==m+1)return 0;
return r[t]-l[t]+1+solve(L,l[t]-1)+solve(r[t]+1,R);
}
bool let;
int main(){
cerr<<(&vio-&let)/1024.0/1024<<endl;
n=rd(),m=rd(),Mn[0]=m+1;
rep(i,1,m){
l[i]=rd(),r[i]=rd();
g[r[i]-l[i]+1].push_back(i);
}
drep(i,n,1){
for(auto x:g[i])Add(l[x],r[x],x);
ans[i]=solve(1,n);
}
rep(i,1,n)printf("%d\n",ans[i]);
return 0;
}

浙公网安备 33010602011771号