Luogu P4198 楼房重建 分块 or 线段树

思路:分块

提交:2次(第一次的求解有问题)

题解:

设块长为$T$,我们开$N/T$个单调栈,维护每一块的上升斜率。

修改时暴力重构整个块,$O(T)$

求解时记录一个最大斜率$lst$,然后块内二分,求出能看见几个,同时更新$lst$

时间复杂度$O(N*(T+frac{N}{T}*log_2T)$,也不知道怎么算最小值,瞎猜$T=sqrt{N*log_2N}$(其实当时算了一下,现在发现算错了,就当是猜的吧$qwq$),后来试了试,定块长$1000$也可以。

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
#define R register int
#define ull unsigned long long
#define ll long long
#define pause (for(R i=1;i<=10000000000;++i))
#define In freopen("NOIPAK++.in","r",stdin)
#define Out freopen("out.out","w",stdout)
namespace Fread {
static char B[1<<15],*S=B,*D=B;
#ifndef JACK
#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
#endif
inline int g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
    if(ch==EOF) return EOF; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
} inline bool isempty(const char& ch) {return (ch<=36||ch>=127);}
inline void gs(char* s) {
    register char ch; while(isempty(ch=getchar()));
    do *s++=ch; while(!isempty(ch=getchar()));
}
} using Fread::g; using Fread::gs;

namespace Luitaryi {
const int N=100010;
int n,m,T;
int pos[N],l[1300],r[1300];
double a[N];
struct STK {
    double stk[1300]; int top;
    inline int calc(double x) {
        R l=1,r=top+1;
        while(l<r) {
            R md=l+r>>1;
            if(stk[md]<=x) l=md+1; else r=md;
        } 
        return top+1-l;
    }
}s[1300];
inline void main() {
    n=g(),m=g(); T=sqrt(n*log2(n)); 
    for(R i=1;i<=n;++i) pos[i]=(i-1)/T+1;
    for(R i=1,lim=pos[n];i<=lim;++i) l[i]=(i-1)*T+1;
    for(R i=1,lim=pos[n];i<lim;++i) r[i]=i*T; r[pos[n]]=min(pos[n]*T,n);
    while(m--) { R ans=0;
        R x=g(),y=g(); R p=pos[x]; 
        a[x]=1.0*y/x; s[p].top=0;
        for(R i=l[p],lim=r[p];i<=lim;++i) 
            s[p].stk[s[p].top]<a[i]?s[p].stk[++s[p].top]=a[i]:0;
        register double lst=0.0;
        for(R i=1;i<=pos[n];++i) 
            ans+=s[i].calc(lst),lst=max(lst,s[i].stk[s[i].top]);
        printf("%d
",ans);
    }
}
}
signed main() {
    Luitaryi::main();
}

线段树的先咕着$QwQ$


2019.07.20

原文地址:https://www.cnblogs.com/Jackpei/p/11217436.html