zoukankan      html  css  js  c++  java
  • [arc063F]Snuke's Coloring 2-[线段树+观察]

    Description

    传送门

    Solution

    我们先不考虑周长,只考虑长和宽。

    依题意得答案下限为max(w+1,h+1),并且最后所得一定是个矩形(矩形内部无点)。

    好的,所以!!!答案一定会经过$y=frac{h}{2}$或$x=frac{w}{2}$。否则答案就。。显然不满足下限了啊。

    我们先考虑答案经过$y=frac{h}{2}$的情况。另一种情况同理(或者把图翻过来也可以)

    我们维护两个单调栈和一个线段树。一个栈a维护直线下方的递减y序列和序列内点的编号,另一个栈b维护直线上方的递增y序列和序列内点的编号,线段树的叶子节点(代表点j)为由当前节点i到j+1所能取到的竖直方向最大值减去x[j](也可理解为矩阵的一条边在j处)。这样ans就为max(ans,x[i+1]+maxn[1])。这里的maxn[1]是指线段树根节点。线段树维护最大值。

    单调栈和线段树的更新:对于新添进来的节点i,如果a[top].y<y[i],则线段树区间[a[top].id,i-1]这一段区间减去y[i]-a[top].y;对于b的更新同理。最后添加(id=i,y=0)到a栈,(id=i,y=h)到b栈,(h-x[i])到线段树代表区间为[i,i]的节点。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define x first
    #define y second 
    using namespace std;
    int w,h,n;
    struct P{int x,y;
    friend bool operator<(P a,P b) {return a.x==b.x?a.y<b.y:a.x<b.x;}}p[300010];
     
    int mx[1200010],tag[1200010];
    int tp1,tp2,nxt;
    pair<int,int> l[300010],r[300010];
    void downtag(int k){mx[k<<1]+=tag[k];mx[k<<1|1]+=tag[k];
    tag[k<<1]+=tag[k];tag[k<<1|1]+=tag[k];tag[k]=0;}
    void modify(int k,int l,int r,int askx,int asky,int x)
    {
        if (askx<=l&&r<=asky) {tag[k]+=x;mx[k]+=x;return;}
        int mid=(l+r)/2;
        if (tag[k]) downtag(k);
        if (askx<=mid) modify(k<<1,l,mid,askx,asky,x);
        if (asky>mid) modify(k<<1|1,mid+1,r,askx,asky,x);
        mx[k]=max(mx[k<<1],mx[k<<1|1]);
    }
    int ans=0;
    void solve()
    {
        memset(mx,0,sizeof(mx));
        memset(tag,0,sizeof(tag));
        sort(p+1,p+n+1);
        tp1=tp2=0;
        for (int i=1;i<=n;i++)
        {
            if (p[i].y<=h/2)
            {
                nxt=i-1;
                while (tp1&&p[i].y>l[tp1].y)
                {
                    modify(1,1,n,l[tp1].x,nxt,l[tp1].y-p[i].y);
                    nxt=l[tp1].x-1;tp1--;
                }
                if (nxt!=i-1) l[++tp1]=make_pair(nxt+1,p[i].y);
            }
            else
            {
                nxt=i-1;
                while (tp2&&p[i].y<r[tp2].y)
                {
                    modify(1,1,n,r[tp2].x,nxt,p[i].y-r[tp2].y);
                    nxt=r[tp2].x-1;tp2--;
                }
                if (nxt!=i-1) r[++tp2]=make_pair(nxt+1,p[i].y);
            }
            l[++tp1]=make_pair(i,0);
            r[++tp2]=make_pair(i,h);
            modify(1,1,n,i,i,h-p[i].x);
            ans=max(ans,p[i+1].x+mx[1]);
        }
    }
    int main()
    {
        scanf("%d%d%d",&w,&h,&n);
        for (int i=1;i<=n;i++) scanf("%d%d",&p[i].x,&p[i].y);
        p[++n]=P{0,0};p[++n]=P{w,h};
        solve();
        for (int i=1;i<=n;i++) swap(p[i].x,p[i].y);swap(w,h);
        solve();
        printf("%d",ans<<1);
    }
  • 相关阅读:
    IntelliJ IDEA 如何在同一个窗口创建多个项目--超详细教程
    spring IOC原理
    java工作错误总结
    java跬步积累
    简单易懂设计模式——简单工厂模式
    Argo 项目入驻 CNCF,一文解析 Kubernetes 原生工作流
    电子书下载 | 超实用!阿里售后专家的 K8s 问题排查案例合集
    在生产环境中,阿里云如何构建高性能云原生容器网络?(含 PPT 下载)
    SIG Cloud Provider Alibaba 网研会第 2 期顺利召开 | 云原生生态周报 Vol. 46
    提问赠书 | 我们请了 7 位云原生专家,等你来问
  • 原文地址:https://www.cnblogs.com/coco-night/p/9677691.html
Copyright © 2011-2022 走看看