[Treap]JZOJ 4737 金色丝线将瞬间一分为二
分析
这道题显然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"); }
在日渐沉没的世界里,我发现了你。