zoukankan      html  css  js  c++  java
  • BZOJ4826: [Hnoi2017]影魔

    题解:首先  明确需要求什么

    p1对应的价值  max((a[i+1].....a[j-1]))<=min(a[i],a[j])

    p2对应的价值转化成 max((a[i+1].....a[j-1]))<=max(a[i],a[j])-p1对应的对数

    然后通过单调栈维护出比这个数大的前一个和后一个 然后转化主席树模型

    操作一直接主席树维护单点值即可  操作二主席树维护区间加即可(永久化标记) 注意操作二需要去重  到底怎么去重需要读者自己考虑一下

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=2e5+10;
    const double eps=1e-8;
    #define ll long long
    using namespace std;
    struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int n,m,p1,p2,cnt;
    int a[MAXN],st[MAXN],tot,L[MAXN],R[MAXN],rt[MAXN];
    typedef struct node{
    	int l,r,tag,sum1;ll sum2;
    }node;
    node d[MAXN*105];
    void update1(int &x,int y,int l,int r,int t){
    	x=++cnt;d[x]=d[y];d[x].sum1++;
    	if(l==r){d[x].sum2--;d[x].tag--;return ;}
    	int mid=(l+r)>>1;
    	if(t<=mid)update1(d[x].l,d[y].l,l,mid,t);
    	else update1(d[x].r,d[y].r,mid+1,r,t);
    	d[x].sum2=d[d[x].l].sum2+d[d[x].r].sum2+1LL*(r-l+1)*d[x].tag;
    }
    void update2(int &x,int y,int l,int r,int ql,int qr){
    	x=++cnt;d[x]=d[y];
    	if(ql<=l&&r<=qr){d[x].sum2+=(r-l+1);d[x].tag++;return ;}
    	int mid=(l+r)>>1;
    	if(ql<=mid)update2(d[x].l,d[y].l,l,mid,ql,qr);
    	if(qr>mid)update2(d[x].r,d[y].r,mid+1,r,ql,qr);
    	d[x].sum2=d[d[x].l].sum2+d[d[x].r].sum2+1LL*(r-l+1)*d[x].tag;
    }
    int ans;
    void querty1(int x,int y,int l,int r,int ql,int qr){
    	if(ql<=l&&r<=qr){ans+=d[y].sum1-d[x].sum1;return ;}
    	int mid=(l+r)>>1;
    	if(ql<=mid)querty1(d[x].l,d[y].l,l,mid,ql,qr);
    	if(qr>mid)querty1(d[x].r,d[y].r,mid+1,r,ql,qr);
    }
    void querty2(int x,int y,int l,int r,int ql,int qr,int flag){
    	if(ql<=l&&r<=qr){ans+=d[y].sum2-d[x].sum2;ans+=1LL*flag*(r-l+1);return ;}
    	int mid=(l+r)>>1;
    	if(ql<=mid)querty2(d[x].l,d[y].l,l,mid,ql,qr,flag+d[y].tag-d[x].tag);
    	if(qr>mid)querty2(d[x].r,d[y].r,mid+1,r,ql,qr,flag+d[y].tag-d[x].tag);
    }
    int main(){
    	n=read();m=read();p1=read();p2=read();
    	inc(i,1,n)a[i]=read();
    	tot=0;
    	inc(i,1,n){
    		while(tot&&a[st[tot]]<a[i])tot--;
    		if(!tot)L[i]=1;else L[i]=st[tot];
    		st[++tot]=i;
    	}
    	reverse(a+1,a+n+1);
    	tot=0;
    	inc(i,1,n){
    		while(tot&&a[n+1-st[tot]]<a[i])tot--;
    		if(!tot)R[n+1-i]=n;else R[n+1-i]=st[tot];
    		st[++tot]=n+1-i;
    	}
    	reverse(a+1,a+n+1);
    	inc(i,1,n){
    		rt[i]=++cnt;d[rt[i]]=d[rt[i-1]];
    		if(L[i]<i){
    			update2(rt[i],rt[i],1,n,L[i],i-1);
    			if(a[L[i]]>a[i])update1(rt[i],rt[i],1,n,L[i]);			
    		}
    		if(R[i]>i){
    			update2(rt[i],rt[i],1,n,i+1,R[i]);
    			if(a[R[i]]>a[i])update1(rt[i],rt[i],1,n,R[i]);	
    		}
    	}
    	int l,r,res1,res2;
    	while(m--){
    		l=read();r=read();
    		ans=0;querty1(rt[l-1],rt[r],1,n,l,r);res1=ans;
    		ans=0;querty2(rt[l-1],rt[r],1,n,l,r,0);res2=ans;
    		ll ans1=1LL*p1*res1+1LL*p2*(res2-res1);
    		printf("%lld
    ",ans1);
    	}
    	return 0;
    }
    

     

    4826: [Hnoi2017]影魔

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 867  Solved: 516
    [Submit][Status][Discuss]

    Description

    影魔,奈文摩尔,据说有着一个诗人的灵魂。事实上,他吞噬的诗人灵魂早已成千上万。千百年来,他收集了各式各样
    的灵魂,包括诗人、牧师、帝王、乞丐、奴隶、罪人,当然,还有英雄。每一个灵魂,都有着自己的战斗力,而影魔,靠
    这些战斗力提升自己的攻击。奈文摩尔有 n 个灵魂,他们在影魔宽广的体内可以排成一排,从左至右标号 1 到 n。
    第 i个灵魂的战斗力为 k[i],灵魂们以点对的形式为影魔提供攻击力,对于灵魂对 i,j(i<j)来说,若不存在 k[s](i
    <s<j)大于 k[i]或者 k[j],则会为影魔提供 p1 的攻击力(可理解为:当 j=i+1 时,因为不存在满足 i<s<j 的 s,从
    而 k[s]不存在,这时提供 p1 的攻击力;当 j>i+1 时,若max{k[s]|i<s<j}<=min{k[i],k[j]} , 则 提 供 p1 的 攻
     击 力 ); 另 一 种 情 况 , 令 c 为k[i+1],k[i+2],k[i+3]......k[j-1]的最大值,若 c 满足:k[i]<c<k[j],或
    者 k[j]<c<k[i],则会为影魔提供 p2 的攻击力,当这样的 c 不存在时,自然不会提供这 p2 的攻击力;其他情况的
    点对,均不会为影魔提供攻击力。影魔的挚友噬魂鬼在一天造访影魔体内时被这些灵魂吸引住了,他想知道,对于任
    意一段区间[a,b],1<=a<b<=n,位于这些区间中的灵魂对会为影魔提供多少攻击力,即考虑 所有满足a<=i<j<=b 的灵
    魂对 i,j 提供的攻击力之和。顺带一提,灵魂的战斗力组成一个 1 到 n 的排列:k[1],k[2],...,k[n]。

    Input

    第一行 n,m,p1,p2
    第二行 n 个数:k[1],k[2],...,k[n]
    接下来 m 行,每行两个数 a,b,表示询问区间[a,b]中的灵魂对会为影魔提供多少攻击力。
    1 <= n,m <= 200000;1 <= p1,p2 <= 1000

    Output

    共输出 m 行,每行一个答案,依次对应 m 个询问。

    Sample Input

    10 5 2 3
    7 9 5 1 3 10 6 8 2 4
    1 7
    1 9
    1 3
    5 9
    1 5

    Sample Output

    30
    39
    4
    13
    16
  • 相关阅读:
    DynamicObject
    ABP文档
    ABP文档
    ABP文档
    ABP文档
    ABP文档
    ABP文档
    第1张 Maven简介 学习笔记
    lambda表达式10个示例——学习笔记
    对象在内存中初始化的过程?
  • 原文地址:https://www.cnblogs.com/wang9897/p/9743772.html
Copyright © 2011-2022 走看看