分块,在每一块中保存可见的斜率(从左边起点开始递增),对于整个数组,第k个块的最后一个可见块必须比第k+1个块的第一个可见块小

对于分块,复杂度为O(sqrt(n))

HYSBZ - 2957 分块_斜率HYSBZ - 2957 分块_#define_02
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-9;
const int N=100000+10,maxn=1000000+10,inf=0x3f3f3f;

int n,m,num,block;
int l[N],r[N],belong[N];
double h[N];
vector<double>v[N];
void build()//建立块
{
    block=int(sqrt((double)n));
    num=n/block;
    if(n%block)num++;
    for(int i=1;i<=num;i++)
    {
        v[i].clear();
        l[i]=(i-1)*block+1,r[i]=i*block;
    }
    r[num]=n;
    for(int i=1;i<=n;i++)
        belong[i]=(i-1)/block+1;
}
void update(int pos,int p)
{
    v[belong[pos]].clear();//把pos所在的块清空
    h[pos]=(double)p/pos;
    for(int i=l[belong[pos]];i<=r[belong[pos]];i++)//重新建立pos所在的整个块
    {
        if(i==l[belong[pos]])//第一个块确保可以放进来
        {
            v[belong[pos]].pb(h[i]);
            continue;
        }
        if(h[i]>v[belong[pos]][v[belong[pos]].size()-1])//建立递增的块
            v[belong[pos]].pb(h[i]);
    }
}
int query()
{
    int ans=0;
    double maxx=0;
    for(int i=1;i<=num;i++)
    {    //在整个块中二分查找第一个比上一个块最大的值
        int pos=upper_bound(v[i].begin(),v[i].end(),maxx)-v[i].begin();
        if(pos!=v[i].size())
        {
            ans+=v[i].size()-pos;
            maxx=v[i][v[i].size()-1];
        }
    }
    return ans;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(h,0,sizeof h);
        build();
        while(m--)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            update(a,b);
            printf("%d\n",query());
        }
    }
    return 0;
}
/****************

****************/
View Code