首页 > 其他分享 >P8037 [COCI2015-2016#7] Prokletnik

P8037 [COCI2015-2016#7] Prokletnik

时间:2024-08-12 21:16:39浏览次数:7  
标签:pre nxt COCI2015 top stk P8037 2016 ll define

思路:

首先考虑离线。

设 \(Min-nxt_i\) 表示下一个小于 \(a_i\) 处的位置,\(Max-nxt_i\) 表示下一个大于 \(a_i\) 处的位置。

那么 \([l,r]\) 是魔法区间当且仅当:

  • \(r\) 是 \([l,r]\) 的最大值,且 \(r < Min - nxt_l\)。

  • \(r\) 是 \([l,r]\) 的最小值,且 \(r < Max - nxt_l\)。

再令 \(Min-pre_i\) 表示上一个小于 \(a_i\) 处的位置,\(Max-pre_i\) 表示上一个大于 \(a_i\) 处的位置。

那么我们可以对于每个 \(r\),求出对应的 \(l\) 的氛围:

  • 若 \(r\) 是 \([l,r]\) 的最大值,则 \(l \in [Max-pre_r+1,r]\)。

  • 若 \(r\) 是 \([l,r]\) 的最小值,则 \(l \in [Min-pre_r+1,r]\)。

则可以在扫描线扫到 \(r\) 时,对上述两个区间更新答案;注意到对于 \(l\) 的答案是 \(r-l+1\),那么对于区间 \([a,b]\),其的右端点若都是 \(r\),要使得贡献最大,应该选择 \([a,r]\) 区间,但是有些点是无法对 \(r\) 造成贡献的(对于这类点的处理见下文),于是我们需要找到 \([a,b]\) 内最小的能对 \(r\) 造成贡献的点,维护一个 set 二分即可,需要支持删除。

但是我们需要满足 \(r < Min-nxt_l\) 或 \(r<Max-nxt_l\),那么可以在 \(Min-nxt_l\) 和 \(Max-nxt_l\) 处将 \(l\) 此处赋值为无穷小即可。

注意到就算 \(l\) 处被赋值为无穷小,即无法对 \(r\) 与 \(r\) 后面的数造成贡献,但是其本身也有贡献,需要用另外一个线段树维护无法造成新贡献的点的区间最大贡献。

时间复杂度为 \(O((N+Q) \log^2 N)\)。

完整代码:

#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
using namespace std;
typedef double db;
typedef unsigned long long ull;
typedef int ll;
bool Begin;
const ll N=5e5+10;
inline ll read(){
    ll x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')
          f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}
inline void write(ll x){
	if(x<0){
		putchar('-');
		x=-x;
	}
	if(x>9)
	  write(x/10);
	putchar(x%10+'0');
}
ll n,q,l,r,top;
ll a[N],ans[N],stk[N],Mi_pre[N],Ma_pre[N],Mi_nxt[N],Ma_nxt[N];
vector<ll> F[N],G[N];
vector<pi> Q[N];
class St{
public:
    ll X[N<<2];
    void pushup(ll k){
        X[k]=max(X[k<<1],X[k<<1|1]);
    }
    void build(ll k,ll l,ll r){
        X[k]=0;
        if(l==r)
          return ;
        ll mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    void add(ll k,ll l,ll r,ll i,ll v){
        if(l==i&&i==r){
            X[k]=v;
            return ;
        }
        ll mid=(l+r)>>1;
        if(i<=mid)
          add(k<<1,l,mid,i,v);
        else
          add(k<<1|1,mid+1,r,i,v);
        pushup(k);
    }
    ll query(ll k,ll L,ll R,ll l,ll r){
        if(L==l&&r==R)
          return X[k];
        ll mid=(L+R)>>1;
        if(r<=mid)
          return query(k<<1,L,mid,l,r);
        else if(l>mid)
          return query(k<<1|1,mid+1,R,l,r);
        else
          return max(query(k<<1,L,mid,l,mid),query(k<<1|1,mid+1,R,mid+1,r));
    }    
}TT;
class Tree{
public:
    set<ll> S;
    struct Node{
        ll l,r;
        ll Max;
        ll tag;
    }X[N<<2];
    ll get(ll x){
        return (*S.lower_bound(x));
    }
    void add(ll k,ll v){
        ll t=get(X[k].l);
        if(t>X[k].r)
          X[k].Max=-1e9;
        else
          X[k].Max=v-t+1;
        X[k].tag=v;
    }
    void push_down(ll k){
        if(X[k].tag){
            add(k<<1,X[k].tag);
            add(k<<1|1,X[k].tag);
            X[k].tag=0;
        }
    }
    void pushup(ll k){
        X[k].Max=max(X[k<<1].Max,X[k<<1|1].Max);
    }
    void build(ll k,ll l,ll r){
        X[k].l=l,X[k].r=r;
        X[k].tag=X[k].Max=0;
        if(l==r){
            S.insert(l);
            return ;
        }
        ll mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    void add(ll k,ll i,ll v){
        if(X[k].l==i&&i==X[k].r){
            TT.add(1,1,n,i,X[k].Max);
            S.erase(i);
            X[k].Max=v;
            return ;
        }
        push_down(k);
        ll mid=(X[k].l+X[k].r)>>1;
        if(i<=mid)
          add(k<<1,i,v);
        else
          add(k<<1|1,i,v);
        pushup(k);
    }
    void update(ll k,ll l,ll r,ll v){
        if(X[k].l==l&&r==X[k].r){
            //cerr<<"1:"<<l<<' '<<r<<' '<<v<<'\n';
            add(k,v);
            //cerr<<"2:"<<l<<' '<<r<<' '<<X[k].Max<<'\n';
            return ;
        }
        push_down(k);
        ll mid=(X[k].l+X[k].r)>>1;
        if(r<=mid)
          update(k<<1,l,r,v);
        else if(l>mid)
          update(k<<1|1,l,r,v);
        else{
            update(k<<1,l,mid,v);
            update(k<<1|1,mid+1,r,v);
        }
        pushup(k);
        //cerr<<"3:"<<X[k].l<<' '<<X[k].r<<' '<<X[k].Max<<'\n';
    }
    ll query(ll k,ll l,ll r){
        //cerr<<"4:"<<X[k].l<<' '<<X[k].r<<' '<<X[k].Max<<'\n';
        if(X[k].l==l&&r==X[k].r)
          return X[k].Max;
        push_down(k);
        ll mid=(X[k].l+X[k].r)>>1;
        if(r<=mid)
          return query(k<<1,l,r);
        else if(l>mid)
          return query(k<<1|1,l,r);
        else
          return max(query(k<<1,l,mid),query(k<<1|1,mid+1,r));
    }
}T;
bool End;
int main(){
    n=read();
    for(int i=1;i<=n;i++)
      a[i]=read();
    q=read();
    for(int i=1;i<=q;i++){
        l=read(),r=read();
        Q[r].push_back({l,i});
    }
    for(int i=1;i<=n;i++){
        while(top&&a[stk[top]]>a[i]){
            Mi_nxt[stk[top]]=i;
            top--;
        }
        stk[++top]=i;    
    }
    top=0;
    for(int i=1;i<=n;i++){
        while(top&&a[stk[top]]<a[i]){
            Ma_nxt[stk[top]]=i;
            top--;
        }
        stk[++top]=i;
    }
    top=0;
    for(int i=n;i>=1;i--){
        while(top&&a[stk[top]]>a[i]){
            Mi_pre[stk[top]]=i;
            top--;
        }
        stk[++top]=i;  
    }
    top=0;
    for(int i=n;i>=1;i--){
        while(top&&a[stk[top]]<a[i]){
            Ma_pre[stk[top]]=i;
            top--;
        }
        stk[++top]=i;       
    }
    for(int i=1;i<=n;i++){
        F[Mi_nxt[i]].push_back(i);
        G[Ma_nxt[i]].push_back(i);
    }
    T.build(1,1,n);
    TT.build(1,1,n);
    for(int i=1;i<=n;i++){
        for(auto v:F[i])
          T.add(1,v,-1e9);
        T.update(1,Ma_pre[i]+1,i,i);
        for(auto t:Q[i])
          ans[t.se]=max({ans[t.se],T.query(1,t.fi,i),TT.query(1,1,n,t.fi,i)});
    }
    T.build(1,1,n);
    TT.build(1,1,n);
    for(int i=1;i<=n;i++){
        for(auto v:G[i])
          T.add(1,v,-1e9);
        T.update(1,Mi_pre[i]+1,i,i);
        for(auto t:Q[i])
          ans[t.se]=max({ans[t.se],T.query(1,t.fi,i),TT.query(1,1,n,t.fi,i)});
    }
    for(int i=1;i<=q;i++){
        write(ans[i]);
        putchar('\n');
    }
	return 0;
}

标签:pre,nxt,COCI2015,top,stk,P8037,2016,ll,define
From: https://www.cnblogs.com/rgw2010/p/18355760

相关文章

  • [COCI2015-2016#3] NEKAMELEONI 题解
    前言题目链接:洛谷。题意简述你要维护一个序列\(a_i\in[1,k]\)(\(k\leq50\)),支持:单点修改;询问最短的包含全部\(1\simk\)的自区间长度,或报告无解。题目分析我想到了两种做法,写题解以加深印象。方法\(1\):直接用线段树维护只有单点修改,尝试用线段树维护分治。考虑......
  • 什么是核心工具要求,为什么在IATF 16949:2016中如此重要?
    核心工具是在汽车行业质量管理中广泛应用的七种基本工具,也被称为“核心工具七法”或“七大工具”。这些核心工具包括:流程流程图(ProcessFlowDiagram)、实验设计(DesignofExperiments)、散点图(ScatterPlot)、直方图(Histogram)、控制图(ControlChart)、故障模式和影响分析(FMEA)以及......
  • 如何进行IATF 16949:2016的内部审核?
    进行IATF16949:2016的内部审核是确保组织质量管理体系符合标准要求并持续改进的重要步骤。以下是进行IATF16949:2016内部审核的一般步骤和流程:1.准备阶段:   -任命内部审核员:选择经过培训和资质认证的内部审核员负责执行内部审核。   -制定审核计划:确定审核的范......
  • 【YashanDB数据库】大事务回滚导致其他操作无法执行,报错YAS-02016 no free undo block
    问题现象客户将一个100G的表的数据插入到另一个表中,使用insertintoselect插入数据。从第一天下午2点开始执行,到第二天上午10点,一直未执行完毕。由于需要实施下一步操作,客户kill重启了数据库,之后数据库一直回滚中,导致后续执行其他操作都报错YAS-02016nofreeundoblocks问题......
  • [COCI2015-2016#3] NEKAMELEONI 题解
    前言题目链接:LOJ;洛谷。题意简述在二叉树上,不断删除叶子,你要维护其树链剖分后重儿子编号和。如果两个孩子大小相同,在一开始连向左儿子,或者保持修改前的连接。\(n\leq2\times10^5\)。题目分析有分块的、有二分的,那我来讲一讲我的想法——树剖维护树剖。首先反转操作,不断......
  • P2831 [NOIP2016 提高组] 愤怒的小鸟
    思路:考虑先求出经过\((x_1,y_1),(x_2,y_2)\)的抛物线解析式我们有:\[\begin{cases}ax_1^2+bx_1=y_1\\ax_2^2+bx_2=y_2\end{cases}\]考虑将\(b\)消掉,求出\(a\)。那么考虑令\(1\)式减去\(2\)式的\(\frac{x_1}{x_2}\)倍:\[ax_1^2+bx_1-ax_1x_2-bx_1......
  • 计算机基础(Windows 10+Office 2016)教程 —— 第7章 演示文稿软件PowerPoint 2016
    第7章演示文稿软件PowerPoint20167.1PowerPoint2016入门7.1.1PowerPoint2016简介7.1.2PowerPoint2016的操作界面组成7.1.3PowerPoint2016的窗口视图方式7.1.4PowerPoint2016的演示文稿及其操作7.1.5PowerPoint2016的幻灯片及其操作7.2演示文稿的编......
  • 计算机基础(Windows 10+Office 2016)教程 —— 第8章 多媒体技术及应用
    多媒体技术及应用8.1多媒体技术的概述8.1.1多媒体技术的定义和特点8.1.2多媒体的关键技术8.1.3多媒体技术的发展趋势8.1.4多媒体文件格式的转换8.1.5多媒体技术的应用8.2多媒体计算机系统的构成8.2.1多媒体计算机系统的硬件系统8.2.2多媒体计算机系统的软......
  • [题解]P6927 [ICPC2016 WF] Swap Space
    思路显然要按\(a_i,b_i\)的大小关系分类:\(a_i<b_i\):假令有两对数\((a_1,b_1),(a_2,b_2)\),且\(a_1\leqa_2\)。如果\(b_1\geqa_2\)。则按照12的顺序,将带来\(a_1\)的花费,以及\(b_1+b_2\)的额外空间;而按照21的顺序,将带来\(a_2\)的花费,以及\(b_1+b_2......
  • 计算机基础(Windows 10+Office 2016)教程 —— 第5章 文档编辑软件Word 2016(上)
    文档编辑软件Word20165.1Word2016入门5.1.1Word2016简介5.1.2Word2016的启动5.1.3Word2016的窗口组成5.1.4Word2016的视图方式5.1.5Word2016的文档操作5.1.6Word2016的退出5.2Word2016的文本编辑5.2.1输入文本5.2.3插入与删除文本5.2.4复制与......