• [Luogu3769][CH弱省胡策R2]TATT


    luogu

    题意

    其实就是四维偏序。

    sol

    第一维排序,然后就只需要写个(3D-tree)了。
    据说(kD-tree)的单次查询复杂度是(O(n^{1-frac{1}{k}}))。所以这里的复杂度是(O(n^{frac{5}{3}}))

    code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    #define ls t[o].ch[0]
    #define rs t[o].ch[1]
    #define cmin(a,b) (a>b?a=b:a)
    #define cmax(a,b) (a<b?a=b:a)
    const int N = 5e4+5;
    int n,D,root,fa[N],pos[N],lim[2][3],ans,Ans;
    struct node{
    	int d[4],id;
    	bool operator < (const node &b) const
    		{return d[D]<b.d[D];}
    }a[N];
    struct kdtree{int d[3],Min[3],Max[3],ch[2],v,mx;}t[N];
    void mt(int x,int y)
    {
    	for (int i=0;i<3;++i)
    		cmin(t[x].Min[i],t[y].Min[i]),cmax(t[x].Max[i],t[y].Max[i]);
    }
    int build(int l,int r,int d)
    {
    	D=d;int o=l+r>>1;
    	nth_element(a+l,a+o,a+r+1);
    	for (int i=0;i<3;++i)
    		t[o].d[i]=t[o].Min[i]=t[o].Max[i]=a[o].d[i];
    	pos[a[o].id]=o;
    	if (l<o) fa[ls=build(l,o-1,(d+1)%3)]=o,mt(o,ls);
    	if (o<r) fa[rs=build(o+1,r,(d+1)%3)]=o,mt(o,rs);
    	return o;
    }
    bool whole(int o)
    {
    	for (int i=0;i<3;++i)
    		if (t[o].Min[i]<lim[0][i]||t[o].Max[i]>lim[1][i])
    			return false;
    	return true;
    }
    bool in(int o)
    {
    	for (int i=0;i<3;++i)
    		if (t[o].d[i]<lim[0][i]||t[o].d[i]>lim[1][i])
    			return false;
    	return true;
    }
    bool empty(int o)
    {
    	for (int i=0;i<3;++i)
    		if (t[o].Min[i]>lim[1][i]||t[o].Max[i]<lim[0][i])
    			return true;
    	return false;
    }
    void query(int o)
    {
    	if (t[o].mx<=ans) return;
    	if (whole(o)) {cmax(ans,t[o].mx);return;}
    	if (empty(o)) return;
    	if (in(o)) cmax(ans,t[o].v);
    	if (ls) query(ls);if (rs) query(rs);
    }
    bool cmp(node i,node j)
    {
    	for (int k=3;~k;--k)
    		if (i.d[k]^j.d[k])
    			return i.d[k]<j.d[k];
    	return i.id<j.id;
    }
    int main()
    {
    	n=gi();
    	for (int i=1;i<=n;++i)
    	{
    		for (int j=0;j<4;++j) a[i].d[j]=gi();
    		a[i].id=i;
    	}
    	root=build(1,n,0);
    	sort(a+1,a+n+1,cmp);
    	for (int i=1;i<=n;++i)
    	{
    		for (int j=0;j<3;++j) lim[0][j]=0,lim[1][j]=a[i].d[j];
    		ans=0;query(root);++ans;cmax(Ans,ans);
    		t[pos[a[i].id]].v=ans;
    		for (int p=pos[a[i].id];p;p=fa[p]) cmax(t[p].mx,ans);
    	}
    	printf("%d
    ",Ans);return 0;
    }
    
  • 相关阅读:
    使用BackgroundWorker组件进行异步操作编程《转》
    C#多线程控制进度条之长任务操作《转》
    模态进度条窗体实现<转>
    dev xtraReports使用《转》
    客户端IP
    WebService获取服务端硬件信息和客户端IP,MAC,浏览器信息,所在城市《转》
    c#多线程 Invoke方法的使用<转>
    C# windowform进度条《转》
    XtraReports 打印控件的简单使用《转》
    hdu Marriage Match II
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8945938.html
Copyright © 2020-2023  润新知