题目描述
n支队伍一共参加了三场比赛。
一支队伍x认为自己比另一支队伍y强当且仅当x在至少一场比赛中比y的排名高。
求有多少组(x,y),使得x自己觉得比y强,y自己也觉得比x强。
(x, y), (y, x)算一组。
输入描述:
第一行一个整数n,表示队伍数; 接下来n行,每行三个整数a[i], b[i], c[i],分别表示i在第一场、第二场和第三场比赛中的名次;n 最大不超过200000
输出描述:
输出一个整数表示满足条件的(x,y)数;64bit请用lld
示例1
输入
4 1 3 1 2 2 4 4 1 2 3 4 3
输出
5
cdq分治模板题
和陌上花开这题很像
第一维排序,第二份树状数组,第三维cdq分治
#include<stdio.h>
#include<algorithm>
using namespace std;
#define LL long long
typedef struct Res
{
LL x, y, z;
bool operator < (const Res &b) const
{
if(x<b.x || x==b.x && y<b.y || x==b.x && y==b.y && z<b.z)
return 1;
return 0;
}
}Res;
LL ans, n, tre[200005];
Res s[200005], L[200005], R[200005];
void Update(LL x, LL val)
{
while(x<=n)
{
tre[x] += val;
x += x&-x;
}
}
LL Query(LL x)
{
LL ans = 0;
while(x)
{
ans += tre[x];
x -= x&-x;
}
return ans;
}
void Cdq(LL l, LL r)
{
LL i, p, q, m;
if(l==r)
return;
m = (l+r)/2;
for(i=l;i<=r;i++)
{
if(s[i].z<=m)
Update(s[i].y, 1);
else
ans += Query(s[i].y);
}
for(i=l;i<=r;i++)
{
if(s[i].z<=m)
Update(s[i].y, -1);
}
p = q = 0;
for(i=l;i<=r;i++)
{
if(s[i].z<=m)
L[++p] = s[i];
else
R[++q] = s[i];
}
for(i=l;i<=m;i++)
s[i] = L[i-(l-1)];
for(i=m+1;i<=r;i++)
s[i] = R[i-m];
Cdq(l, m);
Cdq(m+1, r);
}
int main(void)
{
LL i;
scanf("%lld", &n);
for(i=1;i<=n;i++)
scanf("%lld%lld%lld", &s[i].x, &s[i].y, &s[i].z);
sort(s+1, s+n+1);
Cdq(1, n);
printf("%lld\n", n*(n-1)/2-ans);
return 0;
}