bzoj4237稻草人

传送门

写了一中午,被自己瓜得无话可说。

cdq的题,然后开始脑补。

写了第一个版本是考虑一半对另一半的贡献,贡献的那一遍维护单调性,没有考虑查询的一半的点之间的影响,一直偏大,14pt。

卡掉的数据:

5

1 5

5 4

2 1

3 2

4 3

然后不知道如何脑抽地写了第二个版本,树状数组乱搞,从挡住的地方往上在数组数组里减,然后被重复挡的部分会被多减,一直偏小,31pt

卡掉的数据

5

1 1

4 2

2 3

5 4

5 5

最终屈服于题解,,智商堪忧,,

按x排序,按y分治,考虑下一半对上一半的影响,上一半维护单增的单调栈,相当于知道这个查询点前一个挡住它的点的位置pos,从该点往后的单减的栈就是答案。

于是下一半维护单减的栈,二分找到其中第一个x大于pos的x的位置,往后的栈大小就是答案。

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
const int N=2e5+7;
typedef long long LL;
using namespace std;
int n,xx[N],yy[N],q1[N],q2[N],top1,top2;
LL ans;

template<typename T> void read(T &x) {
    char ch=getchar(); x=0; T f=1;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

struct node{
    int x,y;
    friend bool operator <(const node&A,const node &B) {
        return A.x<B.x;
    }
}p[N],tp[N];

int ef(int x) {
    int l=1,r=top1,res=0;
    while(l<=r) {
        int mid=((l+r)>>1);
        if(p[q1[mid]].x>x) res=mid,r=mid-1;
        else l=mid+1;
    }
    if(res!=0) res=top1-res+1;
    return res;
}

void cdq(int l,int r) {
    if(l==r) return; 
    int mid=((l+r)>>1),ql=l-1,qr=mid;
    top1=top2=0;
    for(int i=l;i<=r;i++) {
        if(p[i].y<=mid) {
            tp[++ql]=p[i];
            while(top1&&p[q1[top1]].y<p[i].y) top1--;
            q1[++top1]=i;
        }
        else {
            tp[++qr]=p[i];
            while(top2&&p[q2[top2]].y>p[i].y) top2--;
            ans+=ef(p[q2[top2]].x);
            q2[++top2]=i;
        }
    }
    for(int i=l;i<=r;i++) p[i]=tp[i];
    cdq(l,mid); cdq(mid+1,r); 
}

#define DEBUG 
int main() {
#ifdef DEBUG
    freopen("scarecrows.in","r",stdin);
    freopen("scarecrows.out","w",stdout);
#endif
    read(n);
    for(int i=1;i<=n;i++) {
        read(p[i].x); read(p[i].y);
        xx[i]=p[i].x;
        yy[i]=p[i].y;
    }
    sort(xx+1,xx+n+1);
    sort(yy+1,yy+n+1);
    for(int i=1;i<=n;i++) {
        p[i].x=lower_bound(xx+1,xx+n+1,p[i].x)-xx;
        p[i].y=lower_bound(yy+1,yy+n+1,p[i].y)-yy;
    }
    sort(p+1,p+n+1);
    cdq(1,n);
    printf("%lld\n",ans);
    return 0;
}
View Code

 

不管怎么说,bzojSolved数终于突破两位数了,留恋一下,可喜可贺可喜可贺。

 

posted @ 2017-12-21 15:27  啊宸  阅读(135)  评论(0编辑  收藏  举报