zoukankan      html  css  js  c++  java
  • ! AHOI/HNOI2017影魔

    区间新解法


    (n,m2e5)

    SOL:

    (L[i],R[i])分别表示(i)左边和右边第一个比自己大的位置

    1. ((L[i],R[i]))产生(p1)贡献,在(R[i])时刻对(L[i])更新
    2. ((L[i]+1 o i-1,R[i]))产生(p2)贡献,在(R[i])时刻对(L[i]+1 o i-1)更新
    3. ((L[i],i+1 o R[i]-1))产生(p1)贡献,在(L[i])时刻对(i+1 o R[i]-1)更新

    (l-1)查询(l,r)答案(ans1)

    (r)查询(l,r)答案(ans2)

    (ans=ans1-ans2)(仔细想一想)

    神奇的区间求法:若固定一端,另一端为一段区间可采用此方法!!

    为什么不会算重?

    每次找到一个最大值,相当于把序列分成两半,相互不影响

    时间复杂度(O(nlog_n))

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f==1?x:-x;
    }
    const int N=2e5+4;
    struct ques{
    	int t,l,r,x,fl;
    }q[N*5];
    inline bool comp(const ques &a,const ques &b){
    	return a.t==b.t?(!a.fl):a.t<b.t;
    }
    int n,m,p1,p2,tot,a[N],L[N],R[N],t1[N],t2[N],st[N],ans[N];
    inline void add(int x,int v){
    	for(int i=x;i<=n;i+=i&-i){
    		t1[i]+=v;t2[i]+=x*v;
    	}
    }
    inline int ask(int x){
    	int ret=0;
    	for(int i=x;i;i-=i&-i)
    		ret+=(x+1)*t1[i]-t2[i];
    	return ret;
    }
    signed main(){
    	n=read();m=read();p1=read();p2=read();
    	for(int i=1,top=0;i<=n;i++){
    		a[i]=read();
    		while(top&&a[i]>a[st[top]]){R[st[top]]=i;top--;}
    		L[i]=st[top];
    		st[++top]=i; 
    	}
    	for(int i=1;i<=n;i++){
    		if(!R[i])R[i]=n+1;
    		if(R[i]<=n&&L[i])q[++tot]=(ques){R[i],L[i],L[i],p1,0};
    		if(R[i]<=n&&L[i]+1<=i-1)q[++tot]=(ques){R[i],L[i]+1,i-1,p2,0};
    		if(L[i]&&i+1<=R[i]-1)q[++tot]=(ques){L[i],i+1,R[i]-1,p2,0};
    	}
    	for(int i=1,l,r;i<=m;i++){
    		l=read();r=read();
    		ans[i]+=(r-l)*p1;
    		q[++tot]=(ques){l-1,l,r,i,-1};
    		q[++tot]=(ques){r,l,r,i,1};
    	}
    	sort(q+1,q+tot+1,comp);
    	for(int i=1;i<=tot;i++){
    		if(!q[i].fl){
    			add(q[i].l,q[i].x);
    			add(q[i].r+1,-q[i].x);
    		}
    		else{
    			ans[q[i].x]+=q[i].fl*(ask(q[i].r)-ask(q[i].l-1));
    		}
    	}
    	for(int i=1;i<=m;i++)cout<<ans[i]<<"
    ";
    	return (0-0);
    }
    
  • 相关阅读:
    postgresql-磁盘空间不足问题排查
    postgresql-删除重复数据
    postgresql-排序
    磁盘耗时时间
    nginx 报错 The plain HTTP request was sent to HTTPS port
    nodejs使用pkg打包
    npm 设置镜像源
    IDEA通过Ctrl+鼠标滚轮放大/缩小字体
    使 nodejs 代码 在后端运行(nohup)
    加密HSQLDB的.script文件
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12520176.html
Copyright © 2011-2022 走看看