思路
cdq分治的裸题。先把三个属性值离散化,进行cdq分治。设为能够杀死第个人的人数,即满足的的个数,如果,那么第个人就被杀死。但是实际上求出来的答案中存在的情况(分治过程中并不能保证左边区间的最小值严格大于于左边区间最大值,存在二者相等的情况),因此要额外减去这些情况。
先以分别作为第一、第二、第三关键字排序,对值相等的某一段单独考虑,也就是对这一段中的所有求出的的个数,求的过程中用树状数组优化。此外还要考虑值均相等的情况,这些数据要一起维护答案,并一起维护进树状数组,否则就会计算到彼此的贡献。
这题用longlong会T。/kk
代码
#include<bits/stdc++.h>
#define lb(x) x&-x
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef int ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void say() {}
void say_() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void say(T _, T2... oth)
{
Out(_);
putchar('\n');
say(oth...);
}
template <typename T, typename... T2>
inline void say_(T _, T2... oth)
{
Out(_);
putchar(' ');
say_(oth...);
}
/*#################################*/
const ll N=5E5+10;
ll n,m,ans;
ll t[N],vx[N],vy[N],vz[N];
struct Node{
ll x,y,z,die;
void pt()
{
say_(x,y,z,die);
puts("");
}
}a[N];
void add(ll x,ll val)
{
while(x<=m)
{
t[x]+=val;
x+=lb(x);
}
}
ll query(ll x)
{
ll ret=0;
while(x)
{
ret+=t[x];
x-=lb(x);
}
return ret;
}
void cdq(ll l,ll r)
{
if(l==r)
return;
ll mid=(l+r)>>1;
cdq(l,mid);
cdq(mid+1,r);
sort(a+l,a+mid+1,[](const Node &u,const Node &v)
{
if(u.y==v.y)
return u.z>v.z;
return u.y>v.y;
});
sort(a+mid+1,a+r+1,[](const Node &u,const Node &v)
{
if(u.y==v.y)
return u.z>v.z;
return u.y>v.y;
});
ll ind=l;
rep(i,mid+1,r)
{
while(ind<=mid && a[ind].y>a[i].y)
{
add(a[ind].z,1);
++ind;
}
a[i].die+=query(m)-query(a[i].z);
}
rep(i,l,ind-1)
add(a[i].z,-1);
}
void print()
{
}
int main()
{
read(n);
rep(i,1,n)
{
read(a[i].x);
vx[i]=a[i].x;
}
rep(i,1,n)
{
read(a[i].y);
vy[i]=a[i].y;
}
rep(i,1,n)
{
read(a[i].z);
vz[i]=a[i].z;
}
sort(vx+1,vx+n+1);
ll nx=unique(vx+1,vx+n+1)-vx-1;
sort(vy+1,vy+n+1);
ll ny=unique(vy+1,vy+n+1)-vy-1;
sort(vz+1,vz+n+1);
ll nz=unique(vz+1,vz+n+1)-vz-1;
m=nz;
rep(i,1,n)
{
a[i].x=lower_bound(vx+1,vx+nx+1,a[i].x)-vx;
a[i].y=lower_bound(vy+1,vy+ny+1,a[i].y)-vy;
a[i].z=lower_bound(vz+1,vz+nz+1,a[i].z)-vz;
}
sort(a+1,a+n+1,[](const Node &u,const Node &v)
{
if(u.x==v.x)
{
if(u.y==v.y)
return u.z>v.z;
return u.y>v.y;
}
return u.x>v.x;
});
ll l=1,r=0;
while(l<=n)
{
while(r<n && a[r+1].x==a[l].x)
++r;
rep(i,l,r)
{
ll ind=i;
while(ind<r && a[i].y==a[ind+1].y)
++ind;
rep(j,i,ind)
a[j].die-=query(m)-query(a[j].z);
rep(j,i,ind)
add(a[j].z,1);
i=ind;
}
rep(i,l,r)
add(a[i].z,-1);
l=r+1;
}
cdq(1,n);
rep(i,1,n)
ans+=a[i].die>0?1:0;
//print();
say(ans);
}