• JOI2020FinalE 火事


    Link
    首先把询问差分,让询问区间变成一段前缀,然后把询问离线并按时间升序排序。
    (L_i=max{j|j<iwedge a_j>a_i},R_i=min{j|j>iwedge a_j>a_i})(a_{t,i})表示在(t)时刻(i)位置的数。
    我们考虑以序列下标作为横坐标,时间作为纵坐标建出直角坐标系,然后在这个直角坐标系上表示数的增加。
    (i)会在(j-i)时刻覆盖(j),其中(jin(i,R_i))。但是直接这样处理无法计算增量,因为在(i)覆盖(j)之前可能会有(kin(i,j))覆盖了(j)
    简单推理可以发现,所有覆盖都可以表示成以下形式:(L_i)覆盖了([i,R_i))这一段区间,让这一段区间加上了(a_{L_i}-a_i),即({(x,y)|xin[i,R_i)wedge yge x-L_i})这一直角梯形内的点的点权加上(a_{L_i}-a_i)
    那么对于询问((t,p)),答案就是({(x,t)|xle p})的点权和加上初始的(sumlimits_{i=1}^pa_i),后一部分可以利用前缀和统计。
    然后我们考虑将直角梯形转化为两个直角三角形的差,这样我们的修改就变成了({(x,y)|xge awedge yge x-b})这一直角三角形内的点的点权加上(c)。不妨用((a,b,c))来表示这样的一组修改。
    分析可得修改((a,b,c))对询问((t,p))的贡献(保证(tge a))为(c(min(p,t+b)-min(p,a+b-1))=c(min(p,a+b-1)+min(p-t,b)+t))
    不难发现(min)中的两边分别之和修改/询问有关,那么用BIT维护即可。

    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<utility>
    #include<algorithm>
    #define fi first
    #define se second
    using i64=long long;
    using pi=std::pair<int,int>;
    const int N=200007;
    int n,q,top,stk[N],a[N],L[N],R[N];i64 sum[N],ans[N];std::vector<pi>vec[N],query[N];
    int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
    struct BIT
    {
        i64 t[N+N];
        void add(int p,i64 v){for(;p<=n+n;p+=p&-p)t[p]+=v;}
        i64 ask(int p){i64 s=0;for(;p;p^=p&-p)s+=t[p];return s;}
    };
    struct node
    {
        BIT t1,t2;
        void add(int p,i64 v){p+=n,t1.add(1,v),t1.add(p+1,-v),t2.add(p+1,p*v);}
        i64 ask(int p){return p+=n,t1.ask(p)*p+t2.ask(p);}
    }t1,t2;
    int main()
    {
        n=read(),q=read();
        for(int i=1;i<=n;++i) sum[i]=sum[i-1]+(a[i]=read());
        for(int i=1;i<=n;L[i]=stk[top],stk[++top]=i++) while(top&&a[i]>a[stk[top]]) R[stk[top--]]=i;
        for(int i=1;i<=n;++i)
    	if(L[i])
    	{
    	    vec[i-L[i]].push_back({i,a[L[i]]-a[i]});
    	    if(R[i]) vec[R[i]-L[i]].push_back({R[i],a[i]-a[L[i]]});
    	}
        for(int i=1,t,l,r;i<=q;++i) t=read(),l=read(),r=read(),ans[i]=sum[r]-sum[l-1],query[t].push_back({r,i}),query[t].push_back({l-1,-i});
        for(int i=1;i<=n;++i)
        {
    	for(auto x:vec[i]) t1.add(x.fi-i,x.se),t2.add(x.fi-1,x.se);
    	for(auto x:query[i]) x.se>0? ans[x.se]+=t1.ask(x.fi-i)-t2.ask(x.fi):ans[-x.se]-=t1.ask(x.fi-i)-t2.ask(x.fi);
        }
        for(int i=1;i<=q;++i) printf("%lld
    ",ans[i]);
    }
    
  • 相关阅读:
    青魔法圣堂法术 Django的技术栈(持续更新)
    青魔法圣堂法术 Django REST framework (DRF) 框架(持续更新)
    Python无法卸载的解决办法
    Django开发social-auth-app-django 第三方登陆
    【转载】青魔法圣堂法术Django项目知识点汇总
    基于session 的springMvc 国际化
    java导出生成csv文件
    mybatis + log4j 打印mybatis的sql
    spring Mvc + Mybatis 中使用junit
    spring官网项目
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12534625.html
Copyright © 2020-2023  润新知