noip 模拟 草堆

很巧妙的一道题
首先发现一个火焰高度的区间贡献为一个分段一次函数
也就是可以写成 \(a*t+b\) 的形式
Q :为什么分段呢
A : 因为要考虑左右两边比它高的火焰,前面限制它,后面吞并它
询问实际上是求前缀的差值
那我们可以把 \([L,R]\) 转换成 询问区间 \([1,L-1]\)\([1,R]\)
对于一个询问 \([1,R']\)
假设覆盖 \(R'\) 点的火焰编号为 \(i\)
那么我们只需要知道 \([1,i-1]\) 的函数截距和斜率的 \(sum\) 就好了
首先解决第一个问题
找到某一时刻覆盖某一点的火焰编号
其实就是询问一个区间的最大值
第二个问题
我们只需要在每一时刻维护出截距和斜率的前缀和就好了
函数的断点查找比较麻烦

Code


#include <bits/stdc++.h>
#define re register
#define db double
#define int long long
// #define ll long long
#define fr first
#define sc second
#define pir make_pair
// #define memset(a) { for(re int i=1,lim=2*n;i<=lim;i++) for(re int j=1,lim=2*n;j<=lim;j++) a[i][j]=0; }
using namespace std;
#define F(i,a,b) for(re int i=a;i<=b;++i)
#define D(i,a,b) for(re int i=a;i>=b;--i)
#define E(i,a) for(re int i=head[a];i;i=edge[i].nxt)
const int N=2e6+10;
const int maxn=2E5+10;
const int INF=1e9+10;
const int mol=998244353;
inline int read(){
    int x=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9') w=(ch=='-')?-1:1,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*w;
}

int n,q,now,a[maxn],que[maxn],totq,ansl[maxn],g[22][maxn],lg2[maxn],l[maxn],r[maxn];
// struct DATE { int a,b; } L[maxn],R[maxn];
int A[maxn],B[maxn];
struct QUS { int t,l,r,id; } ;
vector<QUS>qus;
inline bool cmp(QUS a,QUS b) { return a.t<b.t; }
struct WOS { int pos,a,b; };
vector<WOS>vec[maxn],vc[maxn];
struct STG {
    int ary[maxn];
    #define lew(x) x&-x
    inline void ins(int pos,int val) { while(pos<=n) { ary[pos]+=val; pos+=lew(pos); } }
    inline int quy(int pos) { int ans=0; while(pos) { ans+=ary[pos]; pos-=lew(pos); } return ans; }
} k1,k2;
inline int getkil(int pos) {
    int l=max(1ll,pos-now),r=pos;
    int k=lg2[r-l+1];
    return a[g[k][l]]>a[g[k][r-(1<<k)+1]]? g[k][l]:g[k][r-(1<<k)+1];
}
inline int query(int pos) {
    int i=getkil(pos);
    // cout<<"kil: "<<i<<' '<<((A[i]+B[i]*now))<<endl;
    return k1.quy(i-1)+k2.quy(i-1)*now+(pos-(A[i]+B[i]*now)+1)*a[i];
}
signed main(void) {
    freopen("o.in","r",stdin); freopen("o.out","w",stdout);
    n=read(); q=read();

    for(re int i=1;i<=n;i++) a[i]=read(),g[0][i]=i;

    for(re int i=2;i<=n;i++) lg2[i]=lg2[i>>1]+1;
    for(re int j=1;j<=20;j++) 
        for(re int i=1;i<=n;i++) {
            g[j][i]= (a[g[j-1][i]]>a[g[j-1][i+(1<<j-1)]])? g[j-1][i]:g[j-1][i+(1<<j-1)];
    }
/*
now=4;
cout<<getkil(5)<<endl;
return 0;
*/
    for(re int i=1,t,l,r;i<=q;i++) { t=read(),l=read(),r=read(); qus.push_back((QUS){ t,l,r,i }); }
    for(re int i=1;i<=n;i++) {
        while(totq>=1&&a[que[totq]]<=a[i]) totq--;
        if(!totq) l[i]=-INF; else l[i]=que[totq];
        que[++totq]=i;
    }
    totq=0;
    for(re int i=n;i>=1;i--) {
        while(totq>=1&&a[que[totq]]<a[i]) totq--;
        if(!totq) r[i]=INF; else r[i]=que[totq];
        que[++totq]=i;
    }

// for(re int i=1;i<=n;i++) cout<<l[i]<<' '<<r[i]<<endl; return 0;

    for(re int i=1,kil1,kil2;i<=n;i++) {
        A[i]=i; B[i]=0;
        kil1=i-l[i]; kil2=r[i]-i;
        // cout<<"now: "<<i<<' '<<kil1<<' '<<kil2<<endl;
        k1.ins(i,a[i]); k2.ins(i,a[i]);
        if(kil1<=n) vc[kil1].push_back((WOS){ i,i+1-kil1,1 });
        if(kil1==kil2) {
            if(kil1<=n) {
                vec[kil1].push_back((WOS){ i,2*(kil1-1)*a[i],-2*a[i] });
                if(kil1<<1<=n) vec[kil1<<1].push_back((WOS){ i,-(2*kil1-1)*a[i],a[i] });
            }
        } else {
            int l1=min(kil1,kil2),l2=max(kil1,kil2);
            if(l1<=n) 
                vec[l1].push_back((WOS){ i,(l1-1)*a[i],-a[i] });
            if(l2<=n) {
                vec[l2].push_back((WOS){ i,a[i]*(l2-1),-a[i] });
                if(l1+l2<=n) vec[l1+l2].push_back((WOS){ i,-(l1+l2-1)*a[i],a[i] });
            }
        }
    }
    sort(qus.begin(),qus.end(),cmp);

// return 0;

    for(re int i=0,t,l,r;i<qus.size();i++) {
        t=qus[i].t; l=qus[i].l; r=qus[i].r;
        // cout<<t<<' '<<l<<' '<<r<<endl;
        while(t>now) {
            now++;
            // cout<<"time update: "<<now<<endl;
            for(re int j=0,pos,a,b;j<vec[now].size();j++) {
                pos=vec[now][j].pos; a=vec[now][j].a; b=vec[now][j].b;
                // cout<<"update ls: "<<pos<<' '<<a<<' '<<b<<endl;
                k1.ins(pos,a); k2.ins(pos,b);
            }
            for(re int j=0,pos,a,b;j<vc[now].size();j++) {
                pos=vc[now][j].pos; a=vc[now][j].a; b=vc[now][j].b;
                // cout<<"update print: "<<pos<<' '<<a<<' '<<b<<endl;
                A[pos]=a; B[pos]=b;
            }
        }
        // if(l==2&&r==5) cout<<"check: "<<query(r)<<' '<<query(l-1)<<endl;
        ansl[qus[i].id]=query(r)-query(l-1);
        // cout<<ansl[qus[i].id]<<endl;
    }
    for(re int i=1;i<=q;i++) printf("%lld\n",ansl[i]);
}

posted @ 2021-10-18 10:30  zJx-Lm  阅读(51)  评论(1编辑  收藏  举报