zoukankan      html  css  js  c++  java
  • bzoj 4237 稻草人

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4237

    CDQ。然而却不会做。

    **分治的话,只要考虑两部分之间对答案的贡献就行了,不用考虑部分内的。

    所以就只考虑两部分之间构成的矩形。

    考虑枚举上面部分或下面部分的点。不难(?)发现要使用单调栈。因为另一部分的种种限制很符合单调栈的样子。

    同时自己枚举的这部分也要弄单调栈。这样就能知道本部分中第一个限制自己的点的位置,进而把这个位置到自己之间的所有另一部分符合要求的点加到答案里。

    枚举上面部分的点的话,本部分限制自己的点在自己左边;而枚举下面部分的点的话,本部分限制点在右边,就得从右往左推了,比较不顺。所以枚举上面部分的点吧。

    然后另一部分的点只保留在栈里的,二分找到上面部分的限制点(栈里当前点的上一个点)到当前点之间的部分,计入答案。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=2e5+5,INF=1e9+5;
    int n,stack[N],top;
    ll ans;
    struct Node{
        int x,y;
        bool operator<(const Node &k)const
            {return x<k.x;}
    }a[N];
    bool cmp(Node u,Node v){return u.y<v.y;}
    void cdq(int l,int r)
    {
        if(l==r)return;
        int mid=((l+r)>>1);
        cdq(l,mid);cdq(mid+1,r);
        sort(a+l,a+mid+1,cmp);sort(a+mid+1,a+r+1,cmp);
        int k,u=mid+1;
        for(int i=l;i<=mid;i++)
        {    //下面那行导致n^2 
            for(k=i+1;k<=mid&&a[k].x<a[i].x;k++);if(k>mid)k=0;    //故底下赋初值 
            int mn=INF;
            while(a[u].y<a[i].y&&u<r)u++;if(a[u].y<a[i].y)break;
            for(int j=u;j<=r;j++)
            {
                if(a[j].y>a[k].y)break;
                if(a[j].x<mn)ans++,mn=a[j].x;    //故底下赋初值 
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d%d",&a[i].y,&a[i].x);//
        sort(a+1,a+n+1);
        a[0].y=INF;a[0].x=INF;cdq(1,n);
        printf("%lld",ans);
        return 0;
    }
    以为自己写了个nlogn的,其实是n^2logn
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=2e5+5,INF=1e9+5;
    int n,stack1[N],top1,stack2[N],top2;
    ll ans;
    struct Node{
        int x,y;
        bool operator<(const Node &k)const
            {return x<k.x;}
    }a[N];
    bool cmp(Node u,Node v){return u.y<v.y;}
    void cdq(int l,int r)
    {
        if(l==r)return;
        int mid=((l+r)>>1);
        cdq(l,mid);cdq(mid+1,r);
        sort(a+l,a+mid+1,cmp);sort(a+mid+1,a+r+1,cmp);
        top1=top2=0;int j=l;
        for(int i=mid+1;i<=r;i++)
        {
            while(top1&&a[stack1[top1]].x>a[i].x)top1--;stack1[++top1]=i;
            for(;j<=mid&&a[j].y<a[i].y;j++)
                {while(top2&&a[stack2[top2]].x<a[j].x)top2--;stack2[++top2]=j;}
            int L=1,R=top2,as=top2+1;    //如果stack2里一个也没有<==>下面的都在当前点的右边 
            while(L<=R)
            {
                int md=((L+R)>>1);    //下面那个是a[stack2[md]]!!!不是a[md]!!! 
                if(a[stack2[md]].y>a[stack1[top1-1]].y)as=md,R=md-1;    //此处需要对a[0].y赋初值 
                else L=md+1;
            }
            ans+=top2-as+1;
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d%d",&a[i].y,&a[i].x);//
        sort(a+1,a+n+1);
        a[0].y=-1;cdq(1,n);    //坐标>=0 
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    [转]Navicat Premium 12试用期的破解方法
    Redis禁用持久化功能的设置
    阿里云ECS安装的redis服务器,用java代码去连接报错。
    关于Jedis连接Linux上的redis出现 DENIED Redis is running in protected mode问题的解决方案
    修改了jdk在环境变量中的路径怎么cmd中的jdk版本没有变
    阿里云上部署tomcat启动后,通过http不能访问
    【终结篇】不要再问我程序员该如何提高了……
    我是怎么把一个项目带崩的
    eterm和easyfare的官网地址
    java UTC时间和local时间相互转换
  • 原文地址:https://www.cnblogs.com/Narh/p/9231394.html
Copyright © 2011-2022 走看看