zoukankan      html  css  js  c++  java
  • [AH2017/HNOI2017] 影魔

    #include<bits/stdc++.h>
    #define maxn 200010
    using namespace std;
    int a[maxn],st[maxn][2],top,L[maxn],R[maxn],root[2][maxn];
    struct node{int x,y;}A[maxn];
    struct Node{int x,yl,yr;}B[maxn<<1];
    long long num;
    bool cmp1(node p,node q){return p.x<q.x;}
    bool cmp2(Node p,Node q){return p.x<q.x;}
    struct TREE{
    	int lc[maxn*30],rc[maxn*30],tag[maxn*30],tot;
    	long long sum[maxn*30];
    	void insert(int pre,int &k,int l,int r,int opl,int opr){
    		k=++tot;
    		tag[k]=tag[pre];
    		sum[k]=sum[pre]+opr-opl+1;
    		lc[k]=lc[pre];rc[k]=rc[pre];
    		if(l>=opl&&r<=opr){tag[k]++;return;}
    		int mid=(l+r)>>1;
    		if(opr<=mid) insert(lc[pre],lc[k],l,mid,opl,opr);
    		else if(opl>mid) insert(rc[pre],rc[k],mid+1,r,opl,opr);
    		else {
    			insert(lc[pre],lc[k],l,mid,opl,mid);
    			insert(rc[pre],rc[k],mid+1,r,mid+1,opr);
    		}
    	}
    	void query(int x,int pre,int l,int r,int opl,int opr){
    		if(l>=opl&&r<=opr){num+=sum[x]-sum[pre];return;}
    		int mid=(l+r)>>1;
    		if(opr<=mid) {
    			num+=(tag[x]-tag[pre])*(opr-opl+1);
    			query(lc[x],lc[pre],l,mid,opl,opr);
    		}
    		else if(opl>mid) {
    			num+=(tag[x]-tag[pre])*(opr-opl+1);
    			query(rc[x],rc[pre],mid+1,r,opl,opr);
    		}
    		else {
    			num+=(tag[x]-tag[pre])*(mid-opl+1);
    			query(lc[x],lc[pre],l,mid,opl,mid);
    			num+=(tag[x]-tag[pre])*(opr-mid);
    			query(rc[x],rc[pre],mid+1,r,mid+1,opr);
    		}
    	}
    }tr[2];
    int main(){
    	int n,m,p1,p2;
    	scanf("%d%d%d%d",&n,&m,&p1,&p2);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	st[top][0]=n+1;st[top][1]=0;
    	for(int i=1;i<=n;i++){
    		while(top&&a[i]>st[top][0])top--;
    		L[i]=st[top][1];
    		st[++top][0]=a[i];
    		st[top][1]=i;
    	}
    	st[top=0][0]=n+1;
    	st[top][1]=n+1;
    	for(int i=n;i;i--){
    		while(top&&a[i]>st[top][0])top--;
    		R[i]=st[top][1];
    		st[++top][0]=a[i];
    		st[top][1]=i;
    	}
    	int cnt=0;
    	for(int i=1;i<=n;i++)
    		if(L[i]&&R[i]<=n){
    			A[++cnt].x=L[i];
    			A[cnt].y=R[i];
    		}
    	sort(A+1,A+cnt+1,cmp1);
    	int now=1;
    	for(int i=1;i<=cnt;i++){
    		while(now+1<A[i].x)root[0][now+1]=root[0][now],now++;
    		tr[0].insert(root[0][now],root[0][A[i].x],1,n,A[i].y,A[i].y);
    		now=A[i].x;
    	}
    	while(now!=n)root[0][now+1]=root[0][now++];
    	cnt=0;
    	for(int i=1;i<=n;i++){
    		if(R[i]!=i+1 && L[i]){
    			B[++cnt].x=L[i];
    			B[cnt].yl=i+1;
    			B[cnt].yr=R[i]-1;
    		}
    		if(L[i]!=i-1 && R[i]<=n){
    			B[++cnt].x=R[i];
    			B[cnt].yl=L[i]+1;
    			B[cnt].yr=i-1;
    		}
    	}
    	sort(B+1,B+cnt+1,cmp2);
    	now=1;
    	for(int i=1;i<=cnt;i++){
    		while(now+1<B[i].x)root[1][now+1]=root[1][now],now++;
    		tr[1].insert(root[1][now],root[1][B[i].x],1,n,B[i].yl,B[i].yr);
    		now=B[i].x;
    	}
    	while(now!=n)root[1][now+1]=root[1][now++];
    	int l,r;
    	long long ans;
    	while(m--){
    		scanf("%d%d",&l,&r);
    		num=0;
    		tr[0].query(root[0][r],root[0][l-1],1,n,l,r);
    		ans=num*p1;num=0;
    		tr[1].query(root[1][r],root[1][l-1],1,n,l,r);
    		ans+=num*p2;
    		ans+=(r-l)*p1;
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    vscode 前端好用插件汇总
    IE8和IE9下textarea滚动选中的问题
    javascript实现数字整数位每三位一个逗号分隔
    简单枚举(算法竞赛入门经典)
    拓扑排序(算法竞赛入门经典)
    七桥问题--欧拉(算法竞赛入门经典)
    走迷宫问题 算法竞赛入门经典
    ZOJ1008
    ZOJ1163
    HDU 1069 Monkey and Banana
  • 原文地址:https://www.cnblogs.com/mollnn/p/12333390.html
Copyright © 2011-2022 走看看