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]);
    }
    

      

  • 相关阅读:
    CentOS 7下安装Python3.6
    Django项目运行时出现self.status.split(' ',1)[0], self.bytes_sent,ConnectionAbortedError: [WinError 10053] 你的主机中的软件中止了一个已建立的连接。
    pycharm激活码
    CentOS7环境下安装VIM8 并支撑python3
    CentOS7下源码安装mysql
    formset和modelformset
    ModelForm中定制datetimepicker插件
    ModelForm--定制样式
    Django--models字段参数 limit_choices_to
    复习--类的继承
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6813456.html
Copyright © 2011-2022 走看看