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


    https://www.lydsy.com/JudgeOnline/problem.php?id=4826

    年少不知空间贵,相顾mle空流泪。

    和上一道主席树求的东西差不多,求两种对

    1. max(a[(i,j)])<min(a[i],a[j]),[i,j]这一对贡献p1. 

    2. max(a[(i,j)])在a[i],a[j]之间,[i,j]这一对贡献p2.

    第一种和bzoj3956那道一样,但是因为是排列所以没必要去重了。

    第二种同样是单调栈求lp,rp,每个位置的lp分别和[ i+1 , rp-1 ], rp分别和[ lp+1 , i-1 ], 构成了贡献p2的数对。

    因此贡献为p2的数对要区间修改,因为方便(不用downdata)(其实是因为我抄的代码就是标记永久化)所以写了标记永久化,标记永久化真的挺好用的嘻嘻。

     感觉写了这道题终于有点摸到主席树的门路了,其实就是找和维护两个区间进行限制的值(找和维护一个二维块),一层线段树一层前缀和(只是有传递性不一定是实际意义的和)。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 #define LL long long
     8 const int maxn=200010;
     9 LL n,m,p1,p2;
    10 LL a[maxn]={},sta[maxn]={},tail=0;
    11 LL lp[maxn]={},rp[maxn]={},rt[maxn]={};
    12 LL lc[maxn*64]={},rc[maxn*64]={},siz[maxn*64]={},ad[maxn*64]={},tot=0;
    13 struct nod{
    14     LL x,l,r,v;
    15 }e[maxn*4];
    16 LL cnt=0;
    17 bool mcmp(nod aa,nod bb){ return aa.x<bb.x; }
    18 LL read(){
    19     LL w=0,f=1;char ch=getchar();
    20     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    21     while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
    22     return w*f;
    23 }
    24 void build(LL &x,LL y,LL l,LL r,LL z,LL zl,LL zr){
    25     x=++tot;lc[x]=lc[y];rc[x]=rc[y];ad[x]=ad[y];siz[x]=siz[y]+z*(zr-zl+1);
    26     if(zl==l&&r==zr){ad[x]+=z;return;}
    27     LL mid=(l+r)/2;
    28     if(zr<=mid)build(lc[x],lc[y],l,mid,z,zl,zr);
    29     else if(zl>mid) build(rc[x],rc[y],mid+1,r,z,zl,zr);
    30     else {
    31         build(lc[x],lc[y],l,mid,z,zl,mid);
    32         build(rc[x],rc[y],mid+1,r,z,mid+1,zr);
    33     }
    34 }
    35 LL getsum(LL x,LL y,LL l,LL r,LL zl,LL zr){
    36     if(zl==l&&r==zr)return siz[y]-siz[x];
    37     LL mid=(l+r)/2,ans=(ad[y]-ad[x])*(zr-zl+1);
    38     if(zr<=mid)return ans+getsum(lc[x],lc[y],l,mid,zl,zr);
    39     else if(zl>mid) return ans+getsum(rc[x],rc[y],mid+1,r,zl,zr);
    40     else {
    41         return ans+getsum(lc[x],lc[y],l,mid,zl,mid)+getsum(rc[x],rc[y],mid+1,r,mid+1,zr);
    42     }
    43 }
    44 //以上主席树
    45 inline void fir(){
    46     LL i;
    47     a[0]=a[n+1]=(1<<30);
    48     for(i=1;i<=n;++i){
    49         while(a[sta[tail]]<=a[i])tail--;
    50         lp[i]=sta[tail];sta[++tail]=i;
    51     }
    52     sta[0]=n+1;tail=0;
    53     for(i=n;i>0;--i){
    54         while(a[sta[tail]]<=a[i])tail--;
    55         rp[i]=sta[tail];sta[++tail]=i;
    56     }
    57 }
    58 inline void init(LL x,LL l,LL r,LL v){
    59     e[++cnt].x=x;e[cnt].l=l;e[cnt].r=r;e[cnt].v=v;
    60 }
    61 inline void fir2(){
    62     LL i,j;
    63     for(i=1;i<=n;++i){
    64         if(lp[i]!=0&&rp[i]!=n+1)init(lp[i],rp[i],rp[i],p1);
    65         if(i<n)init(i,i+1,i+1,p1);
    66         if(lp[i]!=0&&rp[i]-i>1)init(lp[i],i+1,rp[i]-1,p2);
    67         if(rp[i]!=n+1&&i-lp[i]>1)init(rp[i],lp[i]+1,i-1,p2);
    68     }
    69     sort(e+1,e+cnt+1,mcmp);
    70     for(i=j=1;i<=n;++i){
    71         rt[i]=rt[i-1];
    72         for(;e[j].x==i&&j<=cnt;++j)build(rt[i],rt[i],1,n,e[j].v,e[j].l,e[j].r);
    73     }
    74 }
    75 int main(){
    76     LL i,x,y,ans=0;
    77     n=read();m=read();p1=read();p2=read();
    78     for(i=1;i<=n;++i)a[i]=read();
    79     fir(); fir2();
    80     for(i=1;i<=m;++i){
    81         x=read();y=read();
    82         if(x>y)swap(x,y);
    83         ans=getsum(rt[x-1],rt[y],1,n,x,y);
    84         printf("%lld
    ",ans);
    85     }
    86     return 0;
    87 }
    View Code

  • 相关阅读:
    mysql(一)
    spring
    数据库连接池
    spring jdbctemplate
    HDU-4219-Randomization?
    离线赛总结
    HDU-4507-吉哥系列故事-恨7不成妻
    HDU-1204-糖果大战
    [BZOJ1150][CTSC2007]数据备份
    二分图学习笔记
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8794916.html
Copyright © 2020-2023  润新知