• [CSP-S模拟测试]:陶陶摘苹果(线段树维护单调栈)


    题目传送门(内部题116)


    输入格式

      第一行两个整数$n,m$,如题
      第二行有$n$个整数表示$h_1-h_n(1leqslant h_ileqslant 10^9)$
      接下来有$m$行,每行两个整数,$p,H_p$,表示第$p$个位置的苹果实际高度为$H_p$。


    输出格式

      输出共$m$行,每行一个整数,表示这种修改情况下的答案。


    样例

    样例输入:

    5 3
    1 2 3 4 4
    1 5
    5 5
    2 3

    样例输出:

    1
    5
    3


    数据范围与提示

    样例解释:

      第一种情况 苹果高度为$5 2 3 4 4$,只摘第一个苹果
      第二种情况 苹果高度为$1 2 3 4 5$,陶陶会摘五个苹果
      第三种情况 苹果高度为$1 3 3 4 4$,所以会选择$1,2,4$号位置的苹果

    数据范围:

      对于$20\%$的数据,$n,mleqslant 5,000$
      对于$100\%$的数据,$n,mleqslant 100,000$。


    题解

    做法很多,我的做法是线段树维护单调栈。

    开场$20$分钟切,就是个板子,没什么好说的了……

    时间复杂度:$Theta(nlog^2n)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    #define L(x) x<<1
    #define R(x) x<<1|1
    using namespace std;
    int n,m;
    int a[200001];
    int trmx[500001],trsm[500001];
    int pushup(int x,int l,int r,int w)
    {
    	if(l==r)return trmx[x]>w;int mid=(l+r)>>1;
    	if(trmx[L(x)]<=w)return pushup(R(x),mid+1,r,w);
    	return trsm[x]-trsm[L(x)]+pushup(L(x),l,mid,w);
    }
    void pushup(int x,int l,int r)
    {
    	if(trmx[L(x)]<=trmx[R(x)])trmx[x]=trmx[R(x)];
    	else trmx[x]=trmx[L(x)];int mid=(l+r)>>1;
    	trsm[x]=trsm[L(x)]+pushup(R(x),mid+1,r,trmx[L(x)]);
    }
    void add(int x,int l,int r,int k,int w)
    {
    	if(l==r){trmx[x]=w;trsm[x]=1;return;}
    	int mid=(l+r)>>1;
    	if(k<=mid)add(L(x),l,mid,k,w);
    	else add(R(x),mid+1,r,k,w);
    	pushup(x,l,r);
    }
    pair<int,int> ask(int x,int l,int r,int k,int w)
    {
    	if(l>n)return make_pair(0,0);
    	if(k<=l)return make_pair(max(w,trmx[x]),pushup(x,l,r,w));
    	int mid=(l+r)>>1;
    	if(mid<k)return ask(R(x),mid+1,r,k,w);
    	pair<int,int> flag=ask(L(x),l,mid,k,w);
    	pair<int,int> res=ask(R(x),mid+1,r,k,max(w,flag.first));
    	res.second+=flag.second;
    	return res;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		add(1,1,n,i,a[i]);
    	}
    	for(int i=1;i<=m;i++)
    	{
    		int p,h;
    		scanf("%d%d",&p,&h);
    		add(1,1,n,p,h);
    		printf("%d
    ",ask(1,1,n,1,0).second);
    		add(1,1,n,p,a[p]);
    	}
    	return 0;
    }
    

    rp++

  • 相关阅读:
    JCTF 2014(Reverse)
    JCTF 2014(Misc)
    实验吧CTF题库-密码学(部分)
    第四章 Jinja2模版
    第三章 URL与视图
    flask学习导航主页
    flask调试模式
    rontab踩坑(三):crontab定时任务调度机制与系统时间/时区的不一致
    crontab踩坑(二):Unit crond.service could not be found.
    crontab踩坑(一)
  • 原文地址:https://www.cnblogs.com/wzc521/p/11790403.html
Copyright © 2020-2023  润新知