zoukankan      html  css  js  c++  java
  • ZJOI2012 小蓝的好友

    题目描述:

    bz

    luogu

    题解:

    好久不写$treap$了来水一发。

    $treap$维护dp。

    考虑在这个图上确定一个矩形的三条边,那么至少包含一个关键点的矩形的数量由开口方向的第一个关键点决定。

    然后是这样的一个图:

     

    考虑从下往上做扫描线,对于左右下三条边,我们能取的范围是这样的:

    这个只是对当前的左右下来说的。

    扩展一下,还有这样的:

    这个过程像是堆的遍历。

    考虑动态维护这个堆,发现不会……

    但是善良的出题人写了:

    所以位置是随机的=v=

    所以直接$Treap$维护这个大根堆+左右区间个数了=v=

    同时这个图还有一个性质,就是定住$x$改变$y$时$y$只会变大。

    所以$Treap$在修改的时候节点只会向上转=v=

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 100050;
    const int M = 40050;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    struct Point
    {
        ll x,y;
        Point(){}
        Point(ll x,ll y):x(x),y(y){}
        bool operator < (const Point&a)const{return x!=a.x?x<a.x:y<a.y;}
    }p[N];
    ll r,c,n;
    struct Treap
    {
        int rt,ls[M],rs[M],siz[M];
        ll w[M],k[M];
        void update(int u)
        {
            siz[u] = siz[ls[u]]+siz[rs[u]]+1;
            w[u] = k[u]*(siz[ls[u]]+1)*(siz[rs[u]]+1)+w[ls[u]]+w[rs[u]];
        }
        void lturn(int&u)
        {
            int t = rs[u];rs[u] = ls[t];
            ls[t] = u;siz[t] = siz[u];
            update(u),update(t);u = t;
        }
        void rturn(int&u)
        {
            int t = ls[u];ls[u] = rs[t];
            rs[t] = u;siz[t] = siz[u];
            update(u),update(t);u = t;
        }
        void chg(int&u,int qx,ll qw)
        {
            if(!u)return ;
            if(u==qx)
            {
                k[u] = qw;
                update(u);
                return ;
            }
            if(qx<u)
            {
                chg(ls[u],qx,qw);
                if(k[u]<k[ls[u]])rturn(u);
            }else
            {
                chg(rs[u],qx,qw);
                if(k[u]<k[rs[u]])lturn(u);
            }
            update(u);
        }
        void build(int l,int r,int&u)
        {
            if(l>r)return ;
            u = (l+r)>>1;
            build(l,u-1,ls[u]);
            build(u+1,r,rs[u]);
            update(u);
        }
    }tr;
    int main()
    {
        read(r),read(c),read(n);
        for(int i=1;i<=n;i++)
            read(p[i].x),read(p[i].y);
        tr.build(1,c,tr.rt);
        sort(p+1,p+1+n);
        ll ans = 0;
        for(int i=1,j=1;i<=r;i++)
        {
            while(j<=n&&p[j].x==i)tr.chg(tr.rt,p[j].y,i),j++;
            ans += tr.w[tr.rt];
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    JDK代理(必须代理类要实现一个接口)
    Spring整合jdbc
    Python 之正则匹配
    Spark ML 之 LR逻辑回归实现排序
    Spark 之 读取配置连接Mysql和上传到HDFS
    Spark ML 之 推荐算法项目(上)
    Spark ML 之 推荐算法项目(下)
    Spark ML 之 ALS内存溢出的解决办法
    Spark ML 之 基于协同过滤的召回算法
    Spark ML 特征处理类之 VectorAssembler 向量装配转换器/VectorIndexer
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/11100767.html
Copyright © 2011-2022 走看看