[HNOI2017]影魔


19.3.14

[Luogu3722] [BZOJ4826]

感谢Brave赐予我勇气

给定n个数的排列,m次询问,每次询问询问一个区间内所有子区间的贡献。
每个区间如果两个端点分别是最大值和次大值,我们就算P1的贡献。
如果两个端点一个是最大值,一个不是次大值,我们就算P2的贡献。

因为要处理两个端点的值, 所以我们钦定某一个端点为最大值(这里钦定右端点),同时处理另一个端点的情况。

那么如果要计算左端点是最大值,那么只要把序列反转然后重新计算一次。

考虑计算一个点的值。如果某个点是从右端点出发的当前的最大值。
那么这个点x要和右端点计算P1的贡献。这个点之前到上个最大点之后的点全部计算P2的贡献。
这个可以用个单调栈来维护。

最后还有一部分细节: 在单调栈弹完的时候,必须要把之前的弹出的没处理的元素加上P2的贡献。

\(1.\)转化题意,很多时候可以用单调栈维护区间的信息

\(2.\)一定要分类清楚,单调栈记得最后还要处理一次


19.3.31

以右端点来处理单调栈中维护的左边的信息 , 并把答案更新在线段树上对应的某些左边的区间 ,
然后统计答案时计算左端点和当前点之间的 : [左端点能覆盖的,右端点已经处理到的]

钦定右端点为最大值 , 左边的就把数组翻转过来 , 一共做两遍就好了

当时就要想清楚并且打一遍 , 或者每个周末复习一下一个星期做的题

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define Debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
typedef long long LL;
const int INF=1e9+7;
typedef pair<int,int> pii;
inline LL read(){
    register LL x=0,f=1;register char c=getchar();
    while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
    while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
    return f*x;
}

const int MAXN=2e5+5;

int a[MAXN];LL ans[MAXN];
int n,m,p1,p2;
pii Q[MAXN];
vector <pii> q[MAXN];

struct SGT{
    LL val[MAXN<<2],add[MAXN<<2];
    inline void init(){
        memset(val,0,sizeof val);
        memset(add,0,sizeof add);
    }
#define ls (rt<<1)
#define rs (rt<<1|1)
    inline void pushup(int rt){
        val[rt]=val[ls]+val[rs];
    }
    inline void pushdown(int rt,int l,int r,int mid){
        if(!add[rt]) return;
        add[ls]+=add[rt],val[ls]+=add[rt]*(mid-l+1);
        add[rs]+=add[rt],val[rs]+=add[rt]*(r-mid);
        add[rt]=0;
    }
    inline void modify(int rt,int l,int r,int x,int y,LL z){
        if(x>y) return;
        if(l>=x&&r<=y){
            val[rt]+=z*(r-l+1);
            add[rt]+=z;
            return;
        }
        int mid=(l+r)>>1;
        pushdown(rt,l,r,mid);
        if(x<=mid) modify(ls,l,mid,x,y,z);
        if(mid<y) modify(rs,mid+1,r,x,y,z);
        pushup(rt);
    }
    inline LL query(int rt,int l,int r,int x,int y){
        if(x>y) return 0;
        if(l>=x&&r<=y) return val[rt];
        LL res=0;int mid=(l+r)>>1;
        pushdown(rt,l,r,mid);
        if(x<=mid) res+=query(ls,l,mid,x,y);
        if(mid<y) res+=query(rs,mid+1,r,x,y);
        return res;
    }
#undef ls
#undef rs
}T;

inline void init(){
    n=read(),m=read(),p1=read(),p2=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        Q[i]=pii(x,y);
    }
}

inline void duce(){
    stack <int> s;
    T.init();
    for(int i=1;i<=n;i++){
        int last=i;
        while(!s.empty()&&a[i]>=a[s.top()]){
            if(s.top()+1<last) T.modify(1,1,n,s.top()+1,last-1,p2);//最大值(右端点即i)和非次大值
            T.modify(1,1,n,s.top(),s.top(),p1);//最大值和次大值
            last=s.top();s.pop();
        }
        if(s.empty()) T.modify(1,1,n,1,last-1,p2);
        else T.modify(1,1,n,s.top()+1,last-1,p2);//最后还要处理一次!!
        s.push(i);//上一个点一定在栈里,这非常重要
        for(int j=0;j<q[i].size();j++)
            ans[q[i][j].second]+=T.query(1,1,n,q[i][j].first,i);//处理到右端点了就可以统计答案了,左边能取到哪就算多少贡献
    }
}

inline void solve(){
    for(int i=1;i<=m;i++) q[Q[i].second].push_back(pii(Q[i].first,i));//操作放在右端点,并记录左端点
    duce();
    for(int i=1;i<=n;i++) q[i].clear();
    for(int i=1;i<=m;i++) q[n-Q[i].first+1].push_back(pii(n-Q[i].second+1,i));//以右端点和左端点分别做一次,转化为单调性的问题
    reverse(a+1,a+n+1);
    duce();
    for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
}

int main(){ 
    init();
    solve();
}

转载于:https://www.cnblogs.com/lizehon/p/10532793.html

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值