2020 年 “游族杯” 全国高校程序设计网络挑战赛 Coronavirus Battle(cdq分治+离散化)

题意
对每个三维点(x,y,z),只有在这个单位时间存在一个点位于(x’,y’,z’) { x’<x && y’<y && z’<z}时,这个点才能在这个单位时间存活,求每个点的存活时间

思路
对z轴进行离散化,然后对整体进行cdq分治,求每个点之后有几个点

代码实现

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+5;
const int M=505;
const int INF=0x3f3f3f3f;
const ll LINF=5e18;
const ull sed=31;
const ll mod=19260817;
const double eps=1e-5;
const double PI=acos(-1.0);
typedef pair<int,int>P;
typedef pair<double,double>Pd;
          
template<class T>void read(T &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9') {f|=(ch=='-');ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=f?-x:x;
    return;
}
 
template <typename T> inline void write(T x) 
{
    if(x<0) putchar('-'), x = -x;
    if(x >= 10) write(x/10);
    putchar(x%10+'0');
}
 
int n;
struct loc
{
    ull x,y,z;
    int pos;
    bool flag;
}lcu[N],tmp[N];
int T[N];
ull z[N];

bool cmp(loc a,loc 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;
}

bool cmp1(loc a,loc b)
{
    return a.y<b.y;
}
ull k1,k2;
ull CoronavirusBeats() 
{
    ull k3 = k1, k4 = k2;
    k1 = k4;
    k3 ^= k3 << 23;
    k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
    return k2 + k4;
}
int ans[N];

inline int lowbit(int x) {return x&(-x);}
void add(int x,int val)
{
    for(;x<N;x+=lowbit(x)) T[x]=max(T[x],val);
}
void init(int x)
{
    for(;x<N;x+=lowbit(x)) T[x]=0;
}
int sum(int x)
{
    int ret=0;
    for(;x;x-=lowbit(x)) ret=max(ret,T[x]);
    return ret;
}

void cdq(int l,int r)
{
    if(l==r) return ;
    int mid=(l+r)>>1;
    cdq(l,mid);
    int cnt=0;
    for(int i=l;i<=r;i++) 
    {
        tmp[++cnt]=lcu[i];
        tmp[cnt].flag=(i>mid);
    }
    sort(tmp+1,tmp+1+cnt,cmp1);
    for(int i=1;i<=cnt;i++)
    {
        if(tmp[i].flag) ans[tmp[i].pos]=max(ans[tmp[i].pos],sum(tmp[i].z)+1);
        else add(tmp[i].z,ans[tmp[i].pos]);
    }
    for(int i=1;i<=cnt;i++) if(!tmp[i].flag) init(tmp[i].z);
    cdq(mid+1,r);
}
int main()
{
    //freopen("a.txt","r",stdin);
    read(n);read(k1);read(k2);
    for(int i=1;i<=n;i++)
    {
        lcu[i].x=CoronavirusBeats();
        lcu[i].y=CoronavirusBeats();
        lcu[i].z=z[i]=CoronavirusBeats();
        lcu[i].pos=i;
        ans[i]=1;
    }
    sort(z+1,z+1+n);
    int m=unique(z+1,z+1+n)-z-1;
    for(int i=1;i<=n;i++) lcu[i].z=lower_bound(z+1,z+1+m,lcu[i].z)-z;
    sort(lcu+1,lcu+1+n,cmp);
    cdq(1,n);
    int ret=0;
    for(int i=1;i<=n;i++) ret=max(ans[i],ret);
    printf("%d\n",ret);
    for(int i=1;i<=n;i++)
    {
        if(i!=1) putchar(' ');
        printf("%d",ans[i]-1);
    }
    puts("");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值