zoukankan      html  css  js  c++  java
  • BZOJ 4826 [Hnoi2017]影魔 ——扫描线 单调栈

    首先用单调栈和扫描线处理出每一个数左面最近的比他大的数在$l[i]$,右面最近的比他大的数$r[i]$。

    然后就可以考虑每种贡献是在什么时候产生的。

    1、$(l[i],r[i])$产生$p1$的贡献

    2、$([l[i]]-[i-1],i)$产生$p2$的贡献

    3、$(i,[i+1]-[r[i]])$产生$p2$的贡献。

    然后发现在笛卡尔坐标系中是一些线段和点,然后平行与扫描线的比较好解决。

    但是垂直的就比较麻烦了。

    然后有人用六棵主席树做过去了,也有人用四棵。

    其实只要线段树分两次扫一遍就好了。

    #include <map>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define ll long long
    #define maxn 200005
     
    struct Options{
        int opt; //1 add 0 query
        int x,y,z,d,id;
        Options() {}
        Options(int _opt,int _x,int _y,int _z,int _d)
        {opt=_opt;x=_x;y=_y;z=_z;d=_d;}
        void print()
        {
            printf("Opt %d ( %d , %d , %d ) ID %d D: %d
    ",opt,x,y,z,id,d);
        }
    }q[maxn<<3];
     
    int n,m,p1,p2,a[maxn],cnt=0,sta[maxn],top,l[maxn],r[maxn],_l[maxn],_r[maxn];
    ll ans[maxn],sum[maxn<<3],mark[maxn<<3];
     
    bool cmp1(Options a,Options b)
    {return a.x==b.x?a.opt>b.opt:a.x<b.x;}
    bool cmp2(Options a,Options b)
    {return a.y==b.y?a.opt>b.opt:a.y<b.y;}
     
    void update(int o)
    {sum[o]=sum[o<<1]+sum[o<<1|1];}
     
    void pushdown(int o,int l,int r)
    {
        if (mark[o]!=0)
        {
            int mid=l+r>>1;
            sum[o<<1]+=(mid-l+1)*mark[o];
            sum[o<<1|1]+=(r-mid)*mark[o];
            mark[o<<1]+=mark[o];
            mark[o<<1|1]+=mark[o];
            mark[o]=0;
        }
    }
     
    void modify(int o,int l,int r,int L,int R,int f)
    {
        if (L<=l&&r<=R)
        {
            mark[o]+=f;
            sum[o]+=(r-l+1)*f;
            return;
        }
        int mid=l+r>>1;pushdown(o,l,r);
        if (L<=mid) modify(o<<1,l,mid,L,R,f);
        if (R>mid) modify(o<<1|1,mid+1,r,L,R,f);
        update(o);
    }
     
    ll query(int o,int l,int r,int L,int R)
    {
        if (L<=l&&r<=R) return sum[o];
        int mid=l+r>>1;pushdown(o,l,r);
        if (R<=mid) return query(o<<1,l,mid,L,R);
        if (L>mid) return query(o<<1|1,mid+1,r,L,R);
        return query(o<<1,l,mid,L,R)+query(o<<1|1,mid+1,r,L,R);
    }
     
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&p1,&p2);
        F(i,1,n) scanf("%d",&a[i]);
        F(i,1,m)
        {
            int x,y; scanf("%d%d",&_l[i],&_r[i]); x=_l[i];y=_r[i];
            q[++cnt].id=i;q[cnt].d=1; q[cnt].x=y+1;q[cnt].y=y+1;q[cnt].opt=0;
            q[++cnt].id=i;q[cnt].d=1; q[cnt].x=x;  q[cnt].y=x;  q[cnt].opt=0;
            q[++cnt].id=i;q[cnt].d=-1;q[cnt].x=x;  q[cnt].y=y+1;q[cnt].opt=0;
            q[++cnt].id=i;q[cnt].d=-1;q[cnt].x=y+1;q[cnt].y=x;  q[cnt].opt=0;
        }
        F(i,1,n)
        {
            while(top&&a[sta[top]]<a[i]) top--;
            l[i]=sta[top];
            sta[++top]=i;
        }
        sta[top=0]=n+1;
        D(i,n,1)
        {
            while(top&&a[sta[top]]<a[i]) top--;
            r[i]=sta[top];
            sta[++top]=i;
        }
        F(i,1,n-1)
        {
            q[++cnt].opt=1;q[cnt].x=i+1;q[cnt].y=i+2;q[cnt].z=i+2;q[cnt].d=p1;
        }
        F(i,1,n)
        {
            q[++cnt]=Options(1,l[i]+1,r[i]+1,r[i]+1,p1);
            if (r[i]-1>=i+1) q[++cnt]=Options(1,l[i]+1,i+2,r[i],p2);
        }
        sort(q+1,q+cnt+1,cmp1);
        F(i,1,cnt)
        {
            switch(q[i].opt)
            {
                case 0:ans[q[i].id]+=q[i].d*query(1,1,n+2,1,q[i].y);break;
                case 1:modify(1,1,n+2,q[i].y,q[i].z,q[i].d);break;
            }
        }
        memset(sum,0,sizeof sum); memset(mark,0,sizeof mark);cnt=0;
        F(i,1,m)
        {
            int x,y;x=_l[i];y=_r[i];
            q[++cnt].id=i;q[cnt].d=1; q[cnt].x=y+1;q[cnt].y=y+1;q[cnt].opt=0;
            q[++cnt].id=i;q[cnt].d=1; q[cnt].x=x;  q[cnt].y=x;  q[cnt].opt=0;
            q[++cnt].id=i;q[cnt].d=-1;q[cnt].x=x;  q[cnt].y=y+1;q[cnt].opt=0;
            q[++cnt].id=i;q[cnt].d=-1;q[cnt].x=y+1;q[cnt].y=x;  q[cnt].opt=0;
        }
        F(i,1,n) if (l[i]+1<=i-1) q[++cnt]=Options(1,l[i]+2,r[i]+1,i,p2);
        sort(q+1,q+cnt+1,cmp2);
        F(i,1,cnt)
        {
            switch(q[i].opt)
            {
                case 0:ans[q[i].id]+=q[i].d*query(1,1,n+2,1,q[i].x);break;
                case 1:modify(1,1,n+2,q[i].x,q[i].z,q[i].d);break;
            }
        }
        F(i,1,m) printf("%lld
    ",ans[i]);
    }
    

      

  • 相关阅读:
    How to change hostname on SLE
    How to install starDIct on suse OS?
    python logging usage
    How to reset password for unknow root
    How to use wget ?
    How to only capute sub-matched character by grep
    How to inspect who is caller of func and who is the class of instance
    How to use groovy script on jenkins
    Vim ide for shell development
    linux高性能服务器编程 (二) --IP协议详解
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6813456.html
Copyright © 2011-2022 走看看