ZJOI2012小さな青い友人

件名の説明:

BZ

luogu

ソリューション:

久しぶりの書き込み$ treap $流出のうち。

$ Treap $メンテナンスDP。

この図の三辺に長方形を決定する検討は、少なくとも1つのキー含む数は最初のキーの長方形の開口方向によって決定されます。

このようなグラフは次のようになります。

 

我々が取ることができる範囲はこれで、次の3つの側面についてのために、ボトムアップからの走査線をやって考えてみましょう:

これは、単に現在についてです。

拡張一見、このようなものがあります。

このプロセスは、ヒープ・トラバーサルのようなものです。

......ヒープの動的なメンテナンスを考えるとないことが判明

しかし、人のようなものが話題を書きました:

したがって、位置=ランダム= 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\n",ans);
    return 0;
}
View Code

 

おすすめ

転載: www.cnblogs.com/LiGuanlin1124/p/11100767.html