• 【BZOJ】2253: [2010 Beijing wc]纸箱堆叠


    题意

    三维严格偏序最长链。((n le 50000)

    分析

    按第一维排序然后以第二和第三维作为关键字依次加入一个二维平面,维护前缀矩形最大值。

    题解

    当然可以树套树....可是似乎没有随机化算法快..
    于是我们上加了强剪枝的kdtree....kdtree大法好...

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=50105;
    struct node;
    int A, P, Te=1, top;
    struct ip {
    	int p[3], d;
    	node *ptr;
    	void scan() {
    		for(int i=0; i<3; ++i) {
    			Te=(ll)A*Te%P;
    			p[i]=Te;
    		}
    		sort(p, p+3);
    		swap(p[0], p[1]);
    		swap(p[1], p[2]);
    		d=0; ptr=0;
    	}
    }a[N], *b[N];
    struct node *null;
    struct node {
    	node *c[2], *f;
    	int x[2], y[2], mx;
    	ip *d;
    	void up() {
    		x[0]=min(d->p[0], min(c[0]->x[0], c[1]->x[0]));
    		x[1]=max(d->p[0], max(c[0]->x[1], c[1]->x[1]));
    		y[0]=min(d->p[1], min(c[0]->y[0], c[1]->y[0]));
    		y[1]=max(d->p[1], max(c[0]->y[1], c[1]->y[1]));
    	}
    	void up2() {
    		mx=max(d->d, max(c[0]->mx, c[1]->mx));
    	}
    	bool check(ip *a, int k) {
    		return x[k]<a->p[0] && y[k]<a->p[1];
    	}
    	bool ok(ip *a) {
    		return d->p[0]<a->p[0] && d->p[1]<a->p[1];
    	}
    	void init(ip *a) {
    		c[0]=c[1]=null;
    		x[0]=x[1]=a->p[0];
    		y[0]=y[1]=a->p[1];
    		mx=0;
    		d=a;
    	}
    }Po[N], *iT=Po, *root, *st[N];
    node *newnode(ip *a) {
    	iT->init(a);
    	return iT++;
    }
    int nowDep;
    bool cmp(const ip *x, const ip *y) {
    	return x->p[nowDep]==y->p[nowDep]?x->p[nowDep^1]<y->p[nowDep^1]:x->p[nowDep]<y->p[nowDep];
    }
    void build(int l, int r, node *&x, int dep) {
    	if(l>r) {
    		x=null;
    		return;
    	}
    	nowDep=dep;
    	int mid=(l+r)>>1;
    	nth_element(b+l, b+mid, b+1+r, cmp);
    	x=newnode(b[mid]);
    	b[mid]->ptr=x;
    	build(l, mid-1, x->c[0], dep^1); if(x->c[0]!=null) x->c[0]->f=x;
    	build(mid+1, r, x->c[1], dep^1); if(x->c[1]!=null) x->c[1]->f=x;
    	x->up();
    }
    int askMx;
    void ask(ip *a, node *x) {
    	if(x==null || !x->check(a, 0) || x->mx<=askMx) {
    		return;
    	}
    	if(x->check(a, 1)) {
    		askMx=max(askMx, x->mx);
    	}
    	if(x->ok(a)) askMx=max(askMx, x->d->d);
    	ask(a, x->c[0]);
    	ask(a, x->c[1]);
    }
    void update(node *x) {
    	for(x->up2(); x!=root; x=x->f, x->up2());
    }
    int n;
    int main() {
    	null=iT++;
    	null->x[0]=null->y[0]=~0u>>1;
    	null->x[1]=null->y[1]=-(~0u>>1);
    	null->d=0; null->mx=0;
    	scanf("%d%d%d", &A, &P, &n);
    	for(int i=1; i<=n; ++i) {
    		a[i].scan();
    		b[i]=&a[i];
    	}
    	build(1, n, root, 0);
    	int ans=0;
    	nowDep=2;
    	sort(b+1, b+1+n, cmp);
    	for(int i=1; i<=n; ++i) {
    		askMx=0;
    		ask(b[i], root);
    		b[i]->d=askMx+1;
    		st[++top]=b[i]->ptr;
    		if(i!=n && b[i]->p[2]!=b[i+1]->p[2]) {
    			while(top) update(st[top--]);
    		}
    		ans=max(ans, b[i]->d);
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
  • 相关阅读:
    【php】session读写锁
    【php】set_include_path和get_include_path用法详解
    【php】header下载文件后,文件变大的问题;(ob_clean()清空缓存)
    php反射机制应用
    vue内置组件 transition 和 keep-alive 使用
    vue中$router以及$route的使用
    通过LxRunOffline迁移Win10的Linux子系统
    vue Router——进阶篇
    vue keep-alive
    go语法和特点零碎总结
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4985731.html
Copyright © 2020-2023  润新知