• BZOJ4237 稻草人(分治+树状数组+单调栈)


      如果要询问的某个纵坐标为inf的点左边是否有点能与其构成所要求的矩形,只要用个单调栈就可以了。可以想到用分治来制造单调性。

      按横坐标排序,每次考虑跨过分治中心的矩形。考虑右边的每个点能与左边的哪些点构成矩形。首先这受到右边点的限制,对于每个点用set求出这个范围。然后对所有点按纵坐标从大到小排序,维护一个树状数组,如果是右边的点直接在树状数组上的该范围查询,左边的点则将其加入单调栈并在树状数组上修改。

      常数过大,在darkbzoj上跑了30s,bzoj上T掉了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<set>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 200010
    #define inf 1000000000
    int n,stk[N],b[N],tree[N];
    long long ans=0;
    struct data{int x,y,d;
    }a[N];
    set<int> f;
    bool cmp(const data&a,const data&b)
    {
        return a.x<b.x;
    }
    bool cmp1(const data&a,const data&b)
    {
        return a.y>b.y;
    }
    void add(int k,int x){while (k<=n+1) tree[k]+=x,k+=k&-k;}
    int query(int k){int s=0;while (k) s+=tree[k],k-=k&-k;return s;}
    void solve(int l,int r)
    {
        if (l==r) return;
        int mid=l+r>>1;
        solve(l,mid);
        solve(mid+1,r);
        for (int i=mid+1;i<=r;i++)
        a[i].d=*f.lower_bound(a[i].y),f.insert(a[i].y);
        for (int i=mid+1;i<=r;i++) f.erase(a[i].y);
        sort(a+l,a+mid+1,cmp1);
        sort(a+mid+1,a+r+1,cmp1);
        int x=l-1,top=0;
        for (int i=mid+1;i<=r;i++)
        {
            while (x<mid&&a[x+1].y>a[i].y)
            {
                x++;
                while (top&&a[x].x>a[stk[top]].x) add(a[stk[top]].y,-1),top--;
                stk[++top]=x;add(a[x].y,1);
            }
            ans+=query(a[i].d)-query(a[i].y);
        }
        x=l-1,top=0;
        for (int i=mid+1;i<=r;i++)
        {
            while (x<mid&&a[x+1].y>a[i].y)
            {
                x++;
                while (top&&a[x].x>a[stk[top]].x) add(a[stk[top]].y,1),top--;
                stk[++top]=x;add(a[x].y,-1);
            }
        }
        sort(a+l,a+mid+1,cmp);
        sort(a+mid+1,a+r+1,cmp);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4237.in","r",stdin);
        freopen("bzoj4237.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        for (int i=1;i<=n;i++) a[i].x=read(),b[i]=a[i].y=inf-read();
        sort(b+1,b+n+1);
        for (int i=1;i<=n;i++) a[i].y=lower_bound(b+1,b+n+1,a[i].y)-b;
        sort(a+1,a+n+1,cmp);f.insert(n+1);
        solve(1,n);
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    高级查询相关练习
    高级查询
    CRUD简单查询
    eclipse 实际运用
    控制台输入与Math Random的基本使用
    调用方法
    jQuery 基础语法
    Java第二课 分支与循环
    Java第一课
    网页项目制作收获2
  • 原文地址:https://www.cnblogs.com/Gloid/p/9832328.html
Copyright © 2020-2023  润新知