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);
    }
    
  • 相关阅读:
    September 29th 2017 Week 39th Friday
    September 28th 2017 Week 39th Thursday
    September 27th 2017 Week 39th Wednesday
    September 26th 2017 Week 39th Tuesday
    September 25th 2017 Week 39th Monday
    September 24th 2017 Week 39th Sunday
    angular2 学习笔记 ( Form 表单 )
    angular2 学习笔记 ( Component 组件)
    angular2 学习笔记 ( Http 请求)
    angular2 学习笔记 ( Router 路由 )
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12520176.html
Copyright © 2011-2022 走看看