CF1614E Divan and a Cottage
题目
代码
首先容易想到对于所有的初始温度,其答案一定构成一段一段的区间,然后因为题目强制在线,可以想到每一天后就维护一下当前的答案集合。
容易发现,其实本质就是对于答案大于某一个数的所有数进行区间减,对于答案小于某个数的所有数区间加。(因为刚刚说了构成连续区间)
那么现在的问题就在于如何求出这两段区间。
显然可以线段树上二分来做,需要记录一下区间答案最大值和区间答案最小值。
然后这题需要动态开点,并且在开点的时候才去分配最大值和最小值,而动态开点的过程就在 \(pushdown\) 里面即可,注意边界的判断。
时间复杂度 \(O(n\log n)\) 。
代码
#include
using namespace std;
//#ifdef ONLINE_JUDGE
// #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
// char buf[1<<21],*p1=buf,*p2=buf;
//#endif
template
inline void read(T &x){
x=0;bool f=false;char ch=getchar();
while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template
inline void write(T x){
if(x<0) x=-x,putchar('-');
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
#define ll long long
#define ull unsigned long long
#define ld long double
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define pc putchar
#define PII pair
#define rep(i,x,y) for(register int i=(x);i<=(y);i++)
#define dep(i,y,x) for(register int i=(y);i>=(x);i--)
#define repg(i,x) for(int i=head[x];i;i=nex[i])
#define filp(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define infilp(s) freopen(s".in","r",stdin)
#define outfilp(s) freopen(s".out","w",stdout)
const int MOD=1e9+7;
inline int inc(int x,int y){x+=y;return x>=MOD?x-MOD:x;}
inline int dec(int x,int y){x-=y;return x<0?x+MOD:x;}
inline void incc(int &x,int y){x+=y;if(x>=MOD) x-=MOD;}
inline void decc(int &x,int y){x-=y;if(x<0) x+=MOD;}
inline void chkmin(int &x,int y){if(yx) x=y;}
const int N=2e5+5,M=2e5+5,INF=1e9+7;
int n,las;
int ls[N<<6],rs[N<<6],Maxn[N<<6],Minn[N<<6],tag[N<<6],cur,root;
inline void Newnode(int &x,int l,int r){
x=++cur;
Minn[x]=l,Maxn[x]=r;
return ;
}
inline void Pushup(int x){
Maxn[x]=Maxn[rs[x]];Minn[x]=Minn[ls[x]];
return ;
}
inline void PushDown(int x,int l,int r){
int mid=l+r>>1;
if(!ls[x]) Newnode(ls[x],l,mid);
if(!rs[x]) Newnode(rs[x],mid+1,r);
const int lc=ls[x],rc=rs[x];
Maxn[lc]+=tag[x],Maxn[rc]+=tag[x];
Minn[lc]+=tag[x],Minn[rc]+=tag[x];
tag[lc]+=tag[x],tag[rc]+=tag[x];
tag[x]=0;
Pushup(x);
return ;
}
void Modify(int &x,int l,int r,int ql,int qr,int v){
if(!x) Newnode(x,l,r);
if(ql<=l&&r<=qr) return Maxn[x]+=v,Minn[x]+=v,tag[x]+=v,void();
int mid=l+r>>1;PushDown(x,l,r);
if(ql<=mid) Modify(ls[x],l,mid,ql,qr,v);
if(qr>mid) Modify(rs[x],mid+1,r,ql,qr,v);
Pushup(x);
return ;
}
int Query(int x,int l,int r,int pos){//查询单点真实温度
if(pos==-1) return -1;
if(l==r) return Maxn[x];
int mid=l+r>>1;PushDown(x,l,r);
if(pos<=mid) return Query(ls[x],l,mid,pos);
return Query(rs[x],mid+1,r,pos);
}
int Ql(int x,int l,int r,int pos){//查询温度小于pos的最后一个位置
if(l==r) return l;
// cout<>1;PushDown(x,l,r);
// cout<<"Ql:"<>1;PushDown(x,l,r);
if(Maxn[ls[x]]>pos) return Qr(ls[x],l,mid,pos);
return Qr(rs[x],mid+1,r,pos);
}
signed main(){
// double ST=clock();
// ios::sync_with_stdio(false);
//#ifndef ONLINE_JUDGE
// filp("my");
//#endif
read(n);
Newnode(root,0,1e9);
rep(i,1,n){
int tmp,k,x,p1=-1,p2=-1;
read(tmp),read(k);
if(Maxn[root]>tmp) p1=Qr(root,0,1e9,tmp);
if(Minn[root]tmp) Modify(root,0,1e9,p1,1e9,-1);
if(Minn[root]