您的位置:首页 > 其它

HDU 5324 Boring Class(分治+树状数组)

2015-11-02 12:32 381 查看

题意: 定两个长度为n的数组,L,R,要求一个子序列(可以不连续)使的L递减,R递增。

思路:这道题可以先把R数组离散化转化为二维坐标排序问题类似于HDU4742 

这道题的不同之处在于要求出最后的这个序列下标并且要求字典序最小,所以要改变一下DP的含义,原来的dp[i]表示的含义是以i为结尾的lis,现在改为以i开头的最长下降子序列。这样在分治的时候,只需要先处理区间[M+1, R]然后再用这一部分的dp值更新前一段的dp值即可,dp记录两个值,第一个值是当前递降序列的长度,第二个是当前位置开始的递降序列的下一个元素的下标,其余部分类似于hdu4742.

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
#define mp(a,b) make_pair (a , b)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int MAXN = 50100;
const int INF = 0x3f3f3f3f;
int n, Hash[MAXN];
pii dp[MAXN];
pii C[MAXN];
struct Node {
int y, z, id;
bool operator < (const Node& A) const {
if(y==A.y) return z < A.z;
return y < A.y;
}
} node[MAXN], tmp[MAXN];
int lowbit(int x) {
return x&-x;
}
void update(int x, pii A) {
while(x <= n) {
if(A.first>C[x].first || A.first==C[x].first&&A.second<C[x].second)
C[x] = A;
x += lowbit(x);
}
}
pii query(int x) {
pii ans = mp(0, INF);
while(x > 0) {
if(ans.first<C[x].first || ans.first==C[x].first&&ans.second>C[x].second)
ans = C[x];
x -= lowbit(x);
}
return ans;
}
void clr(int x) {
while(x <= n) C[x] = mp(0, INF), x += lowbit(x);
}
void solve(int L, int R) {
if(L == R) return;
int M = (L+R) >> 1;
solve(M+1, R);
int cnt = 0;
for(int i = L; i <= R; i++) tmp[++cnt] = node[i];
sort(tmp+1, tmp+cnt+1);
for(int i = 1; i <= cnt; i++) {
if(tmp[i].id > M) {
pii shit = dp[tmp[i].id];
shit.second = tmp[i].id;
update(tmp[i].z, shit);
}
else {
pii t = query(tmp[i].z);
t.first++;
if(t.first>dp[tmp[i].id].first || t.first==dp[tmp[i].id].first&&t.second<dp[tmp[i].id].second)
dp[tmp[i].id] = t;
}
}
for(int i = 1; i <= cnt; i++) {
if(tmp[i].id > M) clr(tmp[i].z);
}
solve(L, M);
}
void init() {
for(int i = 1; i <= n; i++) {
C[i] = mp(0, INF);
dp[i] = mp(1, 0);
}
}
int main() {
//freopen("input.txt", "r", stdin);
while(cin >> n) {
init();
for(int i = 1; i <= n; i++) scanf("%d", &node[i].y);
for(int i = 1; i <= n; i++) scanf("%d", &node[i].z), Hash[i] = node[i].z;
sort(Hash+1, Hash+n+1);
int hs = unique(Hash+1, Hash+n+1) - Hash - 1;
for(int i = 1; i <= n; i++) node[i].z = hs + 1 - (lower_bound(Hash+1, Hash+hs+1, node[i].z) - Hash);
for(int i = 1; i <= n; i++) node[i].id = i;
solve(1, n);
pii ans = mp(0, INF);
int flag = 0;
for(int i = 1; i <= n; i++) {
if(ans.first < dp[i].first) ans = dp[i], flag = i;
}
cout << ans.first << endl;
printf("%d", flag);
while(ans.second != 0) {
printf(" %d", ans.second);
ans = dp[ans.second];
}
puts("");
}
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息