牛客 4A Contest (CDQ分治)
n支队伍一共参加了三场比赛。
一支队伍x认为自己比另一支队伍y强当且仅当x在至少一场比赛中比y的排名高。 求有多少组(x,y),使得x自己觉得比y强,y自己也觉得比x强。 (x, y), (y, x)算一组。 合法的二元组一定是一个人的一场比赛高,其余两场低, 枚举高的那一场, 跑三次CDQ分治. 归并合并时不要用$\text{inplace_merge}$, 太慢会被卡#include <iostream> #include <sstream> #include <algorithm> #include <cstdio> #include <math.h> #include <set> #include <map> #include <queue> #include <string> #include <string.h> #include <bitset> #define REP(i,a,n) for(int i=a;i<=n;++i) #define PER(i,a,n) for(int i=n;i>=a;--i) #define hr putchar(10) #define pb push_back #define lc (o<<1) #define rc (lc|1) #define mid ((l+r)>>1) #define ls lc,l,mid #define rs rc,mid+1,r #define x first #define y second #define io std::ios::sync_with_stdio(false) #define endl '\n' #define DB(a) ({REP(__i,1,n) cout<<a[__i]<<' ';hr;}) using namespace std; typedef long long ll; typedef pair<int,int> pii; const int P = 1e9+7, P2 = 998244353, INF = 0x3f3f3f3f; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;} ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;} inline int rd() {int x=0;char p=getchar();while(p<'0'||p>'9')p=getchar();while(p>='0'&&p<='9')x=x*10+p-'0',p=getchar();return x;} //head #ifdef ONLINE_JUDGE const int N = 1e6+10; #else const int N = 111; #endif int n; int a[N], b[N], c[N]; ll ans; struct _ {int a,b,c;} f[N], tmp[N]; bool cmp1(const _ & lhs, const _ & rhs) { if (lhs.a!=rhs.a) return lhs.a>rhs.a; if (lhs.b!=rhs.b) return lhs.b<rhs.b; return lhs.c<rhs.c; } bool cmp2(const _ & lhs, const _ & rhs) { if (lhs.b!=rhs.b) return lhs.b<rhs.b; return lhs.c<rhs.c; } int d[N]; void add(int x, int v) { for (; x<=n; x+=x&-x) d[x]+=v; } void qry(int x) { for (; x; x^=x&-x) ans+=d[x]; } void merge(int l, int r) { if (l==r) return; merge(l,mid),merge(mid+1,r); int now = l, x=l; REP(i,mid+1,r) { while (now<=mid&&f[now].b<=f[i].b) { tmp[x++]=f[now]; add(f[now++].c,1); } tmp[x++]=f[i]; qry(f[i].c); } REP(i,now,mid) tmp[x++]=f[i]; while (now!=l) add(f[--now].c,-1); REP(i,l,r) f[i]=tmp[i]; } void solve() { REP(i,1,n) f[i].a=a[i],f[i].b=b[i],f[i].c=c[i]; sort(f+1,f+1+n,cmp1); merge(1,n); } int main() { scanf("%d", &n); REP(i,1,n) a[i]=rd(),b[i]=rd(),c[i]=rd(); solve(),swap(a,b),solve(),swap(a,c),solve(); printf("%lld\n", ans); }
看了官方题解发现想麻烦了,,, 只需要算出一场高一场低的, 这样就是二维偏序, 可以直接树状数组, 最后再除以2即可.
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
更多精彩