• 【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;
    }
  • 相关阅读:
    前端之HTML补充
    前端之HTML
    mysql 视图,触发器,存储
    mysql 函数 事务
    索引扩展
    mysql数据库索引相关
    mysql 存储过程查询语句
    mysql 单表查询
    mysql 多表连接查询
    js引入的几种简单写法
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4985731.html
Copyright © 2020-2023  润新知