[Luogu4198]
原题解
19.3.21
用线段树维护有关单调栈的问题
不要pushdown , 但是pushup的时候需要特别注意.
19.3.31
这里的\(pushup2\)其实就是几个特判 : 没有 , 直接返回当前区间答案 , 区间长度为\(1\) ,
以及剩下两大类 , 这里有一个模板 :
if(mx[ls]<=tmp) return pushup2(rs,mid+1,r,tmp);
else return pushup2(ls,l,mid,tmp)+len[rt]-len[ls];
细节见代码
#include<cstdio>
#include<algorithm>
using namespace std;
typedef lon7g long LL;
const int INF=1e9+7;
inline LL read(){register LL x=0,f=1;register char c=getchar();while(c<48||c>57){if(c=='-')f=-1;c=getchar();}while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();return f*x;
}const int MAXN=1e5+5;double a[MAXN];
int n,m;struct SGT{int len[MAXN<<2];double mx[MAXN<<2];
#define ls (rt<<1)
#define rs (rt<<1|1)inline void pushup1(int rt){mx[rt]=max(mx[ls],mx[rs]);}inline int pushup2(int rt,int l,int r,double tmp){if(tmp>=mx[rt]) return 0;//这里必须有一个限制的变量 一个判没有if(a[l]>tmp) return len[rt];//一个判最简单情况if(l==r) return len[l]>tmp;//分类讨论清楚:三种情况 不要忘了长度为1的特判int mid=(l+r)>>1;if(mx[ls]<=tmp) return pushup2(rs,mid+1,r,tmp);//最后两大类else return pushup2(ls,l,mid,tmp)+len[rt]-len[ls];//补上右边还能继续递增的,这个模板很重要}inline void modify(int rt,int l,int r,int x,int y){if(l==r&&l==x){mx[rt]=(double)y/x;//这里不要改a[rt]...len[rt]=1;return;}int mid=(l+r)>>1;if(x<=mid) modify(ls,l,mid,x,y);else modify(rs,mid+1,r,x,y);pushup1(rt);len[rt]=len[ls]+pushup2(rs,mid+1,r,mx[ls]);//用左边的限定右边来更新右边,但不需要保存}
#undef ls
#undef rs
}T;int main(){n=read(),m=read();for(int i=1;i<=m;i++){int x=read(),y=read();a[x]=(double)y/x;T.modify(1,1,n,x,y);printf("%d\n",T.len[1]);}
}