Wannafly模拟赛2: A. Contest(Cdq分治)

来源:互联网 发布:js数组添加到指定位置 编辑:程序博客网 时间:2024/04/30 15:25

题目描述

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

输入

41 3 12 2 44 1 23 4 3

输出

5


cdq分治模板题

和陌上花开这题很像

第一维排序,第二份树状数组,第三维cdq分治

#include<stdio.h>#include<algorithm>using namespace std;#define LL long longtypedef 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);elseans += 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];elseR[++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;}


原创粉丝点击