# BZOJ 4826: [Hnoi2017]影魔 单调栈 主席树

## 4826: [Hnoi2017]影魔

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 665  Solved: 382
[Submit][Status][Discuss]

## Input

1 <= n,m <= 200000;1 <= p1,p2 <= 1000

## 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

// 参考了其他题解之后 觉得上面的思路虽然不low但是还是不好做 就放弃了...

i 只会会对[pre[i],[i+1,nt[i]-1]],[[pre[i]+1,i-1],nt[i]] 有贡献

/*

*/

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;

typedef long long ll;

{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void print(ll x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=200100;

struct president_tree{int ls,rs;ll sum,tag;}tr[N*60];
int sz,root[N];

void insert(int &k,int pre,int l,int r,int x,int y,int val)
{
k=++sz;
tr[k]=tr[pre];
tr[k].sum+=1ll*val*(min(y,r)-max(l,x)+1);
if(l>=x && r<=y)
{tr[k].tag+=val;return ;}
int mid=(l+r)>>1;
if(x<=mid) insert(tr[k].ls,tr[pre].ls,l,mid,x,y,val);
if(y>mid) insert(tr[k].rs,tr[pre].rs,mid+1,r,x,y,val);
}

ll query(int k,int l,int r,int x,int y)
{
if((l>=x&&r<=y) || !k) return tr[k].sum;
ll s(0),t(0);
int mid=(l+r)>>1;
if(x<=mid) s=query(tr[k].ls,l,mid,x,y);
if(y>mid) t=query(tr[k].rs,mid+1,r,x,y);
return s+t+1ll*tr[k].tag*(min(y,r)-max(l,x)+1);
}

struct event{int l,r,val;};

int pre[N],nt[N];
vector<event> vec[N];

int a[N],st[N];

int main()
{
register int i,j,l,r,top(0);
for(i=1;i<=n;++i)
{
while(top && a[st[top]]<a[i]) top--;
pre[i]=st[top];
st[++top]=i;
}
top=0;st[top]=n+1;
for(i=n;i;i--)
{
while(top && a[st[top]]<a[i]) top--;
nt[i]=st[top];
st[++top]=i;
}
for(i=1;i<=n;++i)
{
if(i!=n) vec[i].push_back((event){i+1,i+1,p1});
if(pre[i] && nt[i]<=n) vec[pre[i]].push_back((event){nt[i],nt[i],p1});
if(pre[i] && i<nt[i]-1) vec[pre[i]].push_back((event){i+1,nt[i]-1,p2});
if(i>pre[i]+1 && nt[i]<=n) vec[nt[i]].push_back((event){pre[i]+1,i-1,p2});
}
for(i=1;i<=n;++i)
{
root[i]=root[i-1];
for(j=0;j<vec[i].size();++j)
insert(root[i],root[i],1,n,vec[i][j].l,vec[i][j].r,vec[i][j].val);
}
while(m--)
{