[Treap]JZOJ 4737 金色丝线将瞬间一分为二

Description

 

Input

Output

 

Sample Input

5 10
1 1
2 2
3 3
4 4
5 5

Sample Output

4
 

Data Constraint

 

Hint


分析

这道题显然x与y是独立的

然后对于x来说,每次新增的点需要给总距离加上的值分为两部分:

比它小的:比它小的个数*它的值-比它小的总值

比它大的则类似,相反

其实就是把绝对值运算分类讨论了

然后数据规模很大,不能n^2(n方过百万神教万岁!)就考虑nlogn

想到了平衡树(别问我脑子里为什么都是数据结构还是特别优(yu)秀(cun)那种)

打了一波求小于大于

结果WA,嗯。long long 没开

然后T80,嗯。常数过大

然后就懒得去卡常了

#pragma GCC optimize(3)
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long ll;
const int N=6e5+1;
struct Node {
    int l,r,key,sz,cnt;
    ll dat,sm;
}t[N],c[N];
struct Ans {
    ll sum;
    int num;
};
int n;
ll d,ans;

namespace X {
    int cnt,rt;
    
    inline void Update(int x) {
        t[x].sz=t[t[x].l].sz+t[t[x].r].sz+t[x].cnt;
        t[x].sm=t[t[x].l].sm+t[t[x].r].sm+1ll*t[x].dat*t[x].cnt;
    }
    
    inline void L_Rotate(int &x) {
        int s=t[x].r;
        t[x].r=t[s].l;t[s].l=x;
        Update(x);Update(s);
        x=s;
    }
    
    inline void R_Rotate(int &x) {
        int s=t[x].l;
        t[x].l=t[s].r;t[s].r=x;
        Update(x);Update(s);
        x=s;
    }
    
    void Insert(int &x,int dat) {
        if (!x) {
            x=++cnt;t[x].l=t[x].r=0;
            t[x].cnt=t[x].sz=1;t[x].dat=t[x].sm=dat;t[x].key=rand();
            return;
        }
        if (dat==t[x].dat) t[x].cnt++;
        else
        if (dat<t[x].dat) {
            Insert(t[x].l,dat);
            if (t[t[x].l].key<t[x].key) R_Rotate(x);
        }
        else {
            Insert(t[x].r,dat);
            if (t[t[x].r].key<t[x].key) L_Rotate(x);
        }
        Update(x);
    }
    
    inline Ans Get_Lower(int dat) {
        int x=rt,ans=0;
        ll sum=0;
        while (x) {
            if (dat<t[x].dat) x=t[x].l;
            else {
                ans+=t[t[x].l].sz;sum+=t[t[x].l].sm;
                if (dat==t[x].dat) return (Ans){sum,ans};
                ans+=t[x].cnt;sum+=1ll*t[x].dat*t[x].cnt;
                x=t[x].r;
            }
        }
    }
    
    inline Ans Get_Upper(int dat) {
        int x=rt,ans=0;
        ll sum=0;
        while (x) {
            if (dat>t[x].dat) x=t[x].r;
            else {
                ans+=t[t[x].r].sz;sum+=t[t[x].r].sm;
                if (dat==t[x].dat) return (Ans){sum,ans};
                ans+=t[x].cnt;sum+=1ll*t[x].dat*t[x].cnt;
                x=t[x].l;
            }
        }
    }
}

namespace Y {
    int cnt,rt;
    
    inline void Update(int x) {
        c[x].sz=c[c[x].l].sz+c[c[x].r].sz+c[x].cnt;
        c[x].sm=c[c[x].l].sm+c[c[x].r].sm+1ll*c[x].dat*c[x].cnt;
    }
    
    inline void L_Rotate(int &x) {
        int s=c[x].r;
        c[x].r=c[s].l;c[s].l=x;
        Update(x);Update(s);
        x=s;
    }
    
    inline void R_Rotate(int &x) {
        int s=c[x].l;
        c[x].l=c[s].r;c[s].r=x;
        Update(x);Update(s);
        x=s;
    }
    
    inline void Insert(int &x,int dat) {
        if (!x) {
            x=++cnt;c[x].l=c[x].r=0;
            c[x].cnt=c[x].sz=1;c[x].dat=c[x].sm=dat;c[x].key=rand();
            return;
        }
        if (dat==c[x].dat) c[x].cnt++;
        else
        if (dat<c[x].dat) {
            Insert(c[x].l,dat);
            if (c[c[x].l].key<c[x].key) R_Rotate(x);
        }
        else {
            Insert(c[x].r,dat);
            if (c[c[x].r].key<c[x].key) L_Rotate(x);
        }
        Update(x);
    }
    
    inline Ans Get_Lower(int dat) {
        int x=rt,ans=0;
        ll sum=0;
        while (x) {
            if (dat<c[x].dat) x=c[x].l;
            else {
                ans+=c[c[x].l].sz;sum+=c[c[x].l].sm;
                if (dat==c[x].dat) return (Ans){sum,ans};
                ans+=c[x].cnt;sum+=1ll*c[x].dat*c[x].cnt;
                x=c[x].r;
            }
        }
    }
    
    inline Ans Get_Upper(int dat) {
        int x=rt,ans=0;
        ll sum=0;
        while (x) {
            if (dat>c[x].dat) x=c[x].r;
            else {
                ans+=c[c[x].r].sz;sum+=c[c[x].r].sm;
                if (dat==c[x].dat) return (Ans){sum,ans};
                ans+=c[x].cnt;sum+=1ll*c[x].dat*c[x].cnt;
                x=c[x].l;
            }
        }
    }
}

int main() {
    scanf("%d%lld",&n,&d);
    for (int i=1;i<=n;i++) {
        ll x,y;
        scanf("%lld%lld",&x,&y);
        X::Insert(X::rt,x);Y::Insert(Y::rt,y);
        Ans xl=X::Get_Lower(x),xu=X::Get_Upper(x);
        Ans yl=Y::Get_Lower(y),yu=Y::Get_Upper(y);
        ans+=x*xl.num-xl.sum;ans+=xu.sum-x*xu.num;
        ans+=y*yl.num-yl.sum;ans+=yu.sum-y*yu.num;
        if (ans>d) {
            printf("%d",i);
            return 0;
        }
    }
    printf("-1");
}
View Code

 

posted @ 2018-08-21 20:08  Vagari  阅读(167)  评论(0编辑  收藏  举报