bzoj2253 carton stacking

Keywords: C++

Title Link

meaning of the title

Finding strictly ascending subsequence of triples

thinking

Consider violence first

for(int i = 1;i <= n;++i)
    for(int j = 1;j < i;++j)
        if(x[i] > x[j] && y[i] > y[j] && z[i] > z[j]) 
            f[i] = max(f[i],f[j] + 1)

Consider using \ (CDQ \) divide and conquer to optimize this \ (dp \).
The general idea is to rank the first dimension first to ensure that the first dimension is strictly ascending. Then \ (CDQ \) a second dimension. The tree array maintains the third dimension (needs to be discretized first). The maximum value of the maintenance prefix of the tree array is used here.
Two \ (bug s \) have been tuned for a long time.

bug1

Directly applied the three-dimensional partial order of the board. In fact, this question can't be like this when \ (CDQ \)

void cdq(int l,int r) {
    if(r <= l) return;
    cdq(l,mid),cdq(mid + 1,r);
    //......
}

Because before \ (cdq \) to the right, you must make sure that the right has obtained the answer from the left. This is the difference between LIS and 3D partial order.
The correct operation should be

void cdq(int l,int r){
    if(r <= l) return;
    cdq(l,mid);
    //......
    cdq(mid + 1,r)
}

In fact, this \ (bug \) is quite \ (low \) and I feel that I am mentally retarded 2333

bug2

Because the title says it must be strictly incremental. Therefore, the position of \ (mid \) cannot be taken as the middle directly.
You need to find a different location for \ (x[mid] \) and \ (x[mid + 1] \).

Code

/*
* @Author: wxyww
* @Date:   2019-02-15 10:45:05
* @Last Modified time: 2019-02-16 15:29:12
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 300000 + 10;
map<int,int>ma;
ll read() {
    ll x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
int ls[N],tree[N];
struct node {
    int x[10],ans;
}a[N];
ll A,P,n;
int js;
void clear(int pos) {
    while(pos <= js) {
        tree[pos] = 0;
        pos += pos & -pos;
    }
}
void update(int pos,int x) {
    while(pos <= js) {
        tree[pos] = max(x,tree[pos]);
        pos += pos & -pos;
    }
}
int query(int pos) {
    int ret = 0;
    while(pos) {
        ret = max(ret,tree[pos]);
        pos -= pos & -pos;
    }
    return ret;
}
node tmp[N];
bool cmp(node x,node y) {
    if(x.x[1] != y.x[1])
     return x.x[1] < y.x[1];
    if(x.x[2] != y.x[2]) return x.x[2] < y.x[2];
    return x.x[3] < y.x[3];
}
bool cmy(node x,node y) {
    if(x.x[2] != y.x[2]) return x.x[2] < y.x[2];
    return x.x[3] < y.x[3];
}
void cdq(int l,int r) {
    if(r <= l) return;
    //Ensure that the first dimension on the right is strictly larger than that on the left
    sort(a + l,a + r + 1,cmp);
    int mid = (l + r) >> 1;

    int tt = 1e9;
    for(int i = l;i < r;++i) if(a[i].x[1] != a[i + 1].x[1] && abs(mid - i) < abs(mid - tt)) tt = i;
    if(tt == 1e9) return;
    mid = tt;
    //Ensure the order of the second dimension on both sides
    cdq(l,mid);
    sort(a + l,a + mid + 1,cmy);
    sort(a + mid + 1,a + r + 1,cmy);
    int L = l,R = mid + 1,now = l;
    while(L <= mid && R <= r) {
        if(a[L].x[2] <= a[R].x[2]) {
            update(a[L].x[3],a[L].ans);
            ++L;
        }
        else a[R].ans = max(a[R].ans,query(a[R].x[3] - 1) + 1),++R;
    }
    while(R <= r) a[R].ans = max(a[R].ans,query(a[R].x[3] - 1) + 1),++R;
    for(int i = l;i <= L;++i) clear(a[i].x[3]);
    cdq(mid + 1,r);
}
int main() {
    A = read(),P = read(),n = read();
    ll now = 1;
    int tot = 0;
    for(int i = 1;i <= n;++i)
        for(int j = 1;j <= 3;++j)
            ls[++tot] = a[i].x[j] = now = now * A % P,a[i].ans = 1;

    sort(ls + 1,ls + tot + 1);
    ma[ls[1]] = ++js;
    for(int i = 2;i <= tot;++i) if(ls[i] != ls[i - 1]) ma[ls[i]] = ++js;
    for(int i = 1;i <= n;++i) {
        for(int j = 1;j <= 3;++j)
            a[i].x[j] = ma[a[i].x[j]];
        sort(a[i].x + 1,a[i].x + 4);
    }

    cdq(1,n);
    int ans = 0;
    for(int i = 1;i <= n;++i) ans = max(ans,a[i].ans);
    cout<<ans;
    return 0;
}

Posted by everlifefree on Sat, 07 Dec 2019 14:26:57 -0800