线段树维护单调栈

在普通单调栈的基础上支持修改操作,动态维护节点的单调信息,重点是必须具有可合并性

陶陶摘苹果:
每次向序列最后里加一个数,问每次加入的单调递增的栈的长度(从1开始,1必须选)

就是说eps精度误差不要乱用,如果判等要用至少1e-14,搞个1e-6会WA50%

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<iomanip>
#include<algorithm>
#include<bitset>
#include<map>
#include<vector>
#include<deque>
#include<queue>
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define INF 2147483647
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
using namespace std;
inline int re()
{
    int x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int maxn=1e5+100;
#define eps 1e-14
struct node
{
    int ls,rs,len;
   double k;//
}e[maxn*4];int tot;
double ai[maxn];
#define rson e[rt].rs
#define lson e[rt].ls
inline int calc(int rt,int l,int r,double dik)//l--r区间内确定最小值大于(y/x)的区间长度
{
   // if(!rt)return 0;//如果没有这个区间(一个数都没有就return 0)
    if(e[rt].k<=dik)return 0;
    if(ai[l]>dik)return e[rt].len;
    if(l==r)return  e[rt].k>dik;
    int mid=(l+r)>>1;
    if(dik>=e[lson].k)return calc(rson,mid+1,r,dik);
    return calc(lson,l,mid,dik)+e[rt].len-e[lson].len;//这里一定注意,rson的贡献产生于对于整个l--r区间来说,而不是mid+1,r的区间
}
inline void Insert(int &rt,int l,int r,int pos,int x,int y)//在pos位置添加一个y/x的斜率同时维护最值
{
    if(!rt)rt=++tot;
    if(l==r)
    {
        e[rt].len=1;
        e[rt].k=(double)y/x;
        return;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)Insert(lson,l,mid,pos,x,y);
    else Insert(rson,mid+1,r,pos,x,y);//先更新最值
    //然后考虑区间合并
   e[rt].k=max(e[lson].k,e[rson].k);
    e[rt].len=e[lson].len+calc(rson,mid+1,r,e[lson].k);
   // chu("%d--%d的len:%d\n",l,r,e[rt].len);
    
}
int n,m,root;
int main()
{
  // freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    n=re(),m=re();
    _f(i,1,m)
    {
        int ix=re(),iy=re();
        ai[ix]=(double)iy/ix;
        Insert(root,1,n,ix,ix,iy);
        chu("%d\n",e[root].len);
    }
    return 0;
}
/*
3 4
2 4
3 6
1 1000000000
1 1

1
1
1
2

5 6
2 5
3 7
4 5
1 2
2 3
3 4 

*/
posted on 2022-08-07 11:45  HZOI-曹蓉  阅读(96)  评论(0编辑  收藏  举报