UVA live 6667 三维严格LIS
UVA live 6667 三维严格LIS
传送门:https://vjudge.net/problem/UVALive-6667
题意:
每个球都有三个属性值x,y,z,要求最长的严格lis的长度和方案数
题解:
一维LIS很好求,dp一下就行
二维的LIS,将第一维排序后,和第一维一样
那么三维的lis怎么做了,我们很容易想到将第一维排序后分治的写,分了后, 按照y排序,怎么治呢?用树状数组更新前前x的最大值,然后再用dp更新即可
这里需要注意,和陌上花开等板子题不一样,我们这里不能分了左半部分后再直接分右半部分,这个地方卡了我好久。这里的分治运用是用来给dp服务的,我们dp是由前面的状态转移过来,所以,我们要先更新左半边后再去分治右半边
怎么样求严格的LIS呢,第三维查询更新的时候,我们只需要查到b比当前小的即可
即 更新部分由tmp=sum(p[i].z)->sum(p[i].z-1)其余的都和HDU4742三维LIS是一样的了
int tmp = sum(p[i].z - 1) + 1;
dp[p[i].x] = max(dp[p[i].x], tmp);
代码:
#include <set>
#include <map>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
struct node {
int x, y, z;
} p[maxn];
bool cmpx(node A, node B) {
return A.x < B.x;
}
bool cmpy(node A, node B) {
return A.y < B.y;
}
int lowbit(int x) {
return x & (-x);
}
int n;
int dp[maxn];
int Hash[maxn];
int bit[maxn];
void add(int pos, int val) {
while(pos < n + 2) {
bit[pos] = max(bit[pos], val);
pos += lowbit(pos);
}
}
int sum(int pos) {
int res = 0;
while(pos) {
res = max(res, bit[pos]);
pos -= lowbit(pos);
}
return res;
}
void init(int x) {
for(int i = x; i < n + 2; i += lowbit(i))
bit[i] = 0;
}
void CDQ(int l, int r) {
if(l == r) {
return;
}
int mid = (l + r) >> 1;
CDQ(l, mid);
sort(p + l, p + mid + 1, cmpy);
sort(p + mid + 1, p + r + 1, cmpy);
int j = l;
for(int i = mid + 1; i <= r; i++) {
while(j <= mid && p[j].y < p[i].y) {
add(p[j].z, dp[p[j].x]);
j++;
}
//严格上升的话这里更新的地方由z->z-1
int tmp = sum(p[i].z - 1) + 1;
dp[p[i].x] = max(dp[p[i].x], tmp);
}
for(int i = l; i <= mid; i++) init(p[i].z);
sort(p + mid + 1, p + r + 1, cmpx);
CDQ(mid + 1, r);
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d%d", &p[i].y, &p[i].z);
p[i].x = i;
dp[i] = 1;
Hash[i] = p[i].z;
}
sort(Hash + 1, Hash + n + 1);
int cnt = unique(Hash + 1, Hash + n + 1) - Hash - 1;
for(int i = 1; i <= n; i++) {
p[i].z = lower_bound(Hash + 1, Hash + cnt + 1, p[i].z) - Hash;
}
CDQ(1, n);
int ans = 0;
for(int i = 1; i <= n; i++) {
ans = max(ans, dp[i]);
}
printf("%d\n", ans);
return 0;
}
每一个不曾刷题的日子
都是对生命的辜负
从弱小到强大,需要一段时间的沉淀,就是现在了
~buerdepepeqi