zoukankan      html  css  js  c++  java
  • 【BZOJ4826】[Hnoi2017]影魔 单调栈+扫描线

    【BZOJ4826】[Hnoi2017]影魔

    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

    题解:用单调栈求出每个数左边和右边第一个比它大的数的位置,设其为l[i],r[i]。那么这样的点对:

    (l[i],r[i]),(i,i+1)提供p1攻击力
    (l[i]...i-1,r[i]),(l[i],i+1...r[i])提供p2攻击力

    那么这就变成了在二维平面中,一些线段和点有权值,求矩形内的权值和。可以用扫描线解决(+区间修改树状数组)。

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=200010;
    typedef long long ll;
    int n,m,n1,n2,m1,top;
    int v[maxn],lm[maxn],rm[maxn],st[maxn];
    ll p1,p2;
    ll ans[maxn];
    struct sag
    {
    	int sx,sl,sr,sv;
    }s1[maxn<<1],s2[maxn<<1];
    struct QUERY
    {
    	int qx,ql,qr,org,qv;
    }q[maxn<<1];
    struct BIT
    {
    	ll s[maxn];
    	void init(){memset(s,0,sizeof(s));}
    	void updata(int x,ll val)
    	{
    		for(int i=x;i<=n;i+=i&-i)	s[i]+=val;
    	}
    	ll query(int x)
    	{
    		ll ret=0;
    		for(int i=x;i;i-=i&-i)	ret+=s[i];
    		return ret;
    	}
    }sa,sb;
    void modify(int x,ll val)
    {
    	if(x<=0)	return ;
    	sa.updata(x,val),sb.updata(x,val*x);
    }
    ll ask(int x)
    {
    	return (sa.query(n)-sa.query(x))*x+sb.query(x);
    }
    int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    bool cmps(sag a,sag b)
    {
    	return a.sx<b.sx;
    }
    bool cmpq(QUERY a,QUERY b)
    {
    	return a.qx<b.qx;
    }
    int main()
    {
    	n=rd(),m=rd(),p1=rd(),p2=rd();
    	int i,j;
    	for(i=1;i<=n;i++)	v[i]=rd();
    	for(top=0,i=1;i<=n;i++)
    	{
    		while(top&&v[st[top]]<v[i])	rm[st[top--]]=i;
    		lm[i]=st[top],st[++top]=i;
    	}
    	for(i=1;i<=n;i++)
    	{
    		if(lm[i]&&rm[i])	s1[++n1].sx=lm[i],s1[n1].sl=s1[n1].sr=rm[i],s1[n1].sv=p1;
    		if(i<n)	s2[++n2].sx=i+1,s2[n2].sl=s2[n2].sr=i,s2[n2].sv=p1;
    		if(!rm[i])	rm[i]=n+1;
    		if(lm[i]&&rm[i]>i+1)	s1[++n1].sx=lm[i],s1[n1].sl=i+1,s1[n1].sr=rm[i]-1,s1[n1].sv=p2;
    		if(rm[i]<=n&&lm[i]<i-1)	s2[++n2].sx=rm[i],s2[n2].sl=lm[i]+1,s2[n2].sr=i-1,s2[n2].sv=p2;
    	}
    	sort(s1+1,s1+n1+1,cmps),sort(s2+1,s2+n2+1,cmps);
    	for(i=1;i<=m;i++)
    	{
    		q[i].qx=q[i].ql=q[i+m].ql=rd(),q[i+m].qx=q[i].qr=q[i+m].qr=rd();
    		q[i].qx--,q[i].org=i=q[i+m].org=i,q[i].qv=-1,q[i+m].qv=1;
    	}
    	sort(q+1,q+2*m+1,cmpq);
    	for(i=j=1;i<=2*m;i++)
    	{
    		if(!q[i].qx)	continue;
    		for(;j<=n1&&s1[j].sx<=q[i].qx;j++)	modify(s1[j].sl-1,-s1[j].sv),modify(s1[j].sr,s1[j].sv);
    		ans[q[i].org]+=q[i].qv*(ask(q[i].qr)-ask(q[i].ql-1));
    	}
    	sa.init(),sb.init();
    	for(i=j=1;i<=2*m;i++)
    	{
    		if(!q[i].qx)	continue;
    		for(;j<=n2&&s2[j].sx<=q[i].qx;j++)	modify(s2[j].sl-1,-s2[j].sv),modify(s2[j].sr,s2[j].sv);
    		ans[q[i].org]+=q[i].qv*(ask(q[i].qr)-ask(q[i].ql-1));
    	}
    	for(i=1;i<=m;i++)	printf("%lld
    ",ans[i]);
    	return 0;
    }

     

  • 相关阅读:
    微信小程序开发
    layer 弹出框的使用
    [转]如何把别人项目代码修改后 提交到github
    [转载]Github轻松上手1-Git的工作原理与设置
    [学]git 原理学习
    Dynamics CRM Form表单中通过javascript抓取触发change事件字段的属性名
    技巧:多共享动态库中同名对象重复析构问题的解决方法
    The encryption certificate of the relying party trust identified by thumbprint is not valid
    Cannot start service MSSQL$MICROSOFT##WID on computer
    Hive操作语句实例讲解(帮助你了解 桶 bucket)
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7106170.html
Copyright © 2011-2022 走看看