BZOJ 4826:[AH2017 / HNOI2017]作品魔法の走査線BIT

タイトル

BZOJ 4826

LUOGU 3722

質問の意味を簡素化:

長さ\(N- \)配列のための2つの位置の場合\(L、R&LT \)は、それらが間隔である\([L、R] \ ) で得られた最大値と二番目に大きい値、\(P_1 \ )拠出、その結果、最大であることが発生した場合\(P_2 \)貢献。

分析

これは、フォン・ホーエンハイムのことを思い出します。

長い顔の問題を見て、しかし、モデルのうち、質問の独自の意味を要約してみてください...

人々が直面しているこの問題は、実際にはそうではありませんので、私は見に行ってきましたyyb\(ブログ\を)これは質問の意味を理解し、。

私たちは、それだけで、次の作業を行うためには、このプロセスの出すことができ、これはこの区間の最大点間隔でなければならないことを、オーバーラップする2つの寄与ことがわかりました。

すなわち、プロセスの各点\(Iは\)最初の点の左側は、より大きい\(L [I] \)と、第1の点の右側がより大きい\(R&LT [I] \) これはすることができ以下のようなモノトーンのスタックで二回総なめにしました。

それから

  1. その後、間隔の\(Lは、[i]は\)する(R [i]が\)\\(P_1 \)の寄与を、
  2. 左端点用(I-SIM \ L [I]を+1しました1 \)\、右端点\(R [I] \)間隔が有する\(P_2 \)の寄与を、
  3. 左の点のための\(L [I]が\) 右端点\(I + 1 \ SIM R [I] -1 \) 間隔が存在する\(P_2 \)貢献。

だから、オフライン処理することができます。

それから

  1. 我々は、掃引\(R [I] \) 更新点\(L [I] \)の寄与を、
  2. 我々は、掃引\(R [I] \) 更新間隔\(L [i]を+1 \ SIM I-1 \) の寄与を、
  3. 我々は、掃引\([i]が\ Lの)、更新間隔\(I + 1 \ SIM R [I] -1 \) の寄与を。

これは、すべての貢献の範囲に対処します。

各インタロゲーションのために\([L、R&LT] \) 上記3つの場合の全ては、2次元平面上のセグメントを抽象化1、その要求は、この範囲内の当量を要求し、走査線及び間隔は変更\(BITを\)この操作を完了すること。

コード

#include<bits/stdc++.h>

typedef long long ll;
const int maxn=2e5+10;

namespace IO
{
    char buf[1<<15],*fs,*ft;
    inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
    template<typename T>inline void read(T &x)
    {
        x=0;
        T f=1, ch=getchar();
        while (!isdigit(ch) && ch^'-') ch=getchar();
        if (ch=='-') f=-1, ch=getchar();
        while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
        x*=f;
    }

    char Out[1<<24],*fe=Out;
    inline void flush() { fwrite(Out,1,fe-Out,stdout); fe=Out; }
    template<typename T>inline void write(T x,char str)
    {
        if (!x) *fe++=48;
        if (x<0) *fe++='-', x=-x;
        T num=0, ch[20];
        while (x) ch[++num]=x%10+48, x/=10;
        while (num) *fe++=ch[num--];
        *fe++=str;
    }
}

using IO::read;
using IO::write;

int n,m,p1,p2;
namespace BIT
{
    ll c1[maxn],c2[maxn];
    inline int lowbit(int x) { return x & -x; }
    inline void add(int x,int v) { for (int i=x; i<=n; i+=lowbit(i)) c1[i]+=v, c2[i]+=x*v; }
    inline ll ask(int x) { ll ans=0; for (int i=x; i; i-=lowbit(i)) ans+=(x+1)*c1[i]-c2[i]; return ans; }
    inline ll hsh(int l,int r) { return ask(r)-ask(l-1); }
}

using BIT::add;
using BIT::hsh;

struct QwQ{int x,l,r,v,id;}q[maxn<<2];
int cnt;
inline bool cmp1(QwQ a,QwQ b) { return a.x<b.x; }

struct Orz{int x,l,r,v;}o[maxn<<2];
int tot;
inline bool cmp2(Orz a,Orz b) { return a.x<b.x; }

ll ans[maxn]; int L[maxn],R[maxn];
int k[maxn],Stack[maxn],top;
int main()
{
    read(n);read(m);read(p1);read(p2);
    for (int i=1; i<=n; ++i) read(k[i]);
    Stack[top=1]=0;
    for (int i=1; i<=n; ++i)
    {
        while (top>1 && k[Stack[top]]<k[i]) --top;
        L[i]=Stack[top], Stack[++top]=i;
    }
    Stack[top=1]=n+1;
    for (int i=n; i>=1; --i)
    {
        while (top>1 && k[Stack[top]]<k[i]) --top;
        R[i]=Stack[top], Stack[++top]=i;
    }
    for (int i=1,l,r; i<=m; ++i)
    {
        read(l);read(r);
        ans[i]=(r-l)*p1;
        q[++cnt]=(QwQ){r,l,r,1,i};
        q[++cnt]=(QwQ){l-1,l,r,-1,i};
    }
    std::sort(q+1,q+cnt+1,cmp1);
    for (int i=1; i<=n; ++i)
    {
        if (L[i] && R[i]<n+1) o[++tot]=(Orz){R[i],L[i],L[i],p1};
        if (L[i] && R[i]>i+1) o[++tot]=(Orz){L[i],i+1,R[i]-1,p2};
        if (L[i]+1<i && R[i]<n+1) o[++tot]=(Orz){R[i],L[i]+1,i-1,p2};
    }
    std::sort(o+1,o+tot+1,cmp2);
    for (int i=1, j=1; i<=cnt; ++i)
    {
        while (j<=tot && o[j].x<=q[i].x) add(o[j].l,o[j].v), add(o[j].r+1,-o[j].v), ++j;
        ans[q[i].id]+=q[i].v*hsh(q[i].l,q[i].r);
    }
    for (int i=1; i<=m; ++i) write(ans[i],'\n');
    IO::flush();
    return 0;
}

  1. 見て、走査線を使用する理由である2次元平面上の線、にこの抽象アイデアQYP_2002\(ブログ\を)

おすすめ

転載: www.cnblogs.com/G-hsm/p/11449311.html