Wannafly模拟赛2

Contest
时间限制:1秒 空间限制:131072K

题目描述

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

求三维偏序对,在二维的基础上可以进行,这个可以BIT+CDQ啊,但是超时妥妥的

超时代码

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
#define maxn 200002
typedef long long ll;
int T,n,tot,id[maxn];
inline char _getchar()
{
    static const int BUFSIZE = 100001 ;
    static char  buf[BUFSIZE] ;
    static char  *psta=buf, *pend=buf ;
    if (psta >= pend){
        psta = buf;
        pend = buf + fread(buf,1,BUFSIZE,stdin);
        if (psta >= pend)
            return -1;
    }
    return *psta++;
}
inline void read(int &x)
{
    char c;
    int ans=0;
    for(c=getchar(); c<'0'||c>'9'; c=getchar());
    while(c>='0'&&c<='9')
        ans=(ans<<1)+(ans<<3)+(c-'0'),c=getchar();
    x=ans;
}
struct node
{
    int x,y,z,cnt,ans,id;
} p[maxn];
int cmpx(node a,node b)
{
    if(a.x!=b.x)return a.x<b.x;
    if(a.y!=b.y)return a.y<b.y;
    return a.z<b.z;
}
int cmpy(node a,node b)
{
    if(a.y!=b.y)return a.y<b.y;
    return a.z<b.z;
}
int cmpid(node a,node b)
{
    return a.id<b.id;
}
struct BIT
{
#define lowbit(x) (x&(-x))
    int b[maxn];
    void init()
    {
        memset(b,0,sizeof(b));
    }
    void update(int x,int v)
    {
        while(x<=maxn)
        {
            b[x]+=v;
            x+=lowbit(x);
        }
    }
    int query(int x)
    {
        int ans=0;
        while(x)
        {
            ans+=b[x];
            x-=lowbit(x);
        }
        return ans;
    }
    void clear(int x)
    {
        while(x<=maxn)
        {
            b[x]=0;
            x+=lowbit(x);
        }
    }
} bit;
void CDQ(int l,int r)
{
    if(l==r)
    {
        p[l].ans+=p[l].cnt-1;
        return ;
    }
    int mid=(l+r)>>1;
    CDQ(l,mid);
    CDQ(mid+1,r);
    sort(p+l,p+mid+1,cmpy);
    sort(p+mid+1,p+r+1,cmpy);
    int j=l;
    for(int i=mid+1; i<=r; i++)
    {
        for(; j<=mid&&p[j].y<=p[i].y; j++)
            bit.update(p[j].z,p[j].cnt);
        p[i].ans+=bit.query(p[i].z);
    }
    for(int i=l; i<j; i++)bit.update(p[i].z,-p[i].cnt);
    sort(p+l,p+r+1,cmpy);
}
int main()
{
    read(n);
    bit.init();
    tot=0;
    for(int i=1; i<=n; i++)
    {
      read(p[i].x);
      read(p[i].y);
      read(p[i].z);
      p[i].ans=0,p[i].id=i;
    }
    sort(p+1,p+n+1,cmpx);
    for(int i=1; i<=n; i++)
    {
        if(i!=1&&p[i-1].x==p[i].x&&p[i-1].y==p[i].y&&p[i-1].z==p[i].z)
            p[tot].cnt++;
        else p[++tot]=p[i],p[tot].cnt=1;
        id[p[i].id]=tot;
        p[tot].id=tot;
    }
    CDQ(1,tot);
    sort(p+1,p+tot+1,cmpid);
    ll ans=1ll*n*(n-1)/2;
    for(int i=1; i<=n; i++)
    ans-=p[id[i]].ans;
    printf("%lld",ans);
    return 0;
}

为什么要CDQ啊,严重拖慢了时间啊,但是扔到CF上是可以AC的,谁让CF的机器跑的快呢

附上AC代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=200005;
const int K = 450;
struct Point
{
    int x,y,z;
    bool operator < (const Point& rhs) const {return z<rhs.z;}
}p[maxn];
int n,c[maxn/K+5][maxn/K+5];
inline int lowbit(int x) {return x&(-x);}
int query2D(int qx,int qy)
{
    int ret=0;
    while(qy)
    {
        ret+=c[qx][qy];
        qy-=lowbit(qy);
    }
    return ret;
}
int query1D(int qx,int qy)
{
    int ret=0;
    while(qx)
    {
        ret+=query2D(qx,qy);
        qx-=lowbit(qx);
    }
    return ret;
}
void modify2D(int px,int py,int v)
{
    while(py<=(n/K))
    {
        c[px][py]+=v;
        py+=lowbit(py);
    }
}
void modify1D(int px,int py,int v)
{
    while(px<=(n/K))
    {
        modify2D(px,py,v);
        px+=lowbit(px);
    }
}
int X[maxn],Y[maxn];
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
    for(int i=0;i<=n;i++) X[i]=n+1,Y[i]=n+1;
    sort(p,p+n);
    LL ans=(LL)n*(n-1)/2LL;
    for(int i=0;i<n;i++)
    {
        ans-=query1D(p[i].x/K,p[i].y/K);
        for(int j=p[i].x;j>p[i].x-(p[i].x%K);j--) if(Y[j]<p[i].y) ans--;
        for(int j=p[i].y;j>p[i].y-(p[i].y%K);j--) if(X[j]<=p[i].x-(p[i].x%K)) ans--;
        X[p[i].y]=p[i].x,Y[p[i].x]=p[i].y;
        modify1D((p[i].x+K-1)/K,(p[i].y+K-1)/K,1);
    }
    printf("%lld
",ans);
}
原文地址:https://www.cnblogs.com/BobHuang/p/7528788.html