【NOIP2013模拟联考7】最长上升子序列

来源:互联网 发布:medline数据库论文 编辑:程序博客网 时间:2024/06/05 21:10

Description:

维护一个序列,使它可以进行下面两种操作:
1.在末尾添加一个数字x
2.将整个序列变成第x次操作后的样子
在每次操作后,输出当前序列的最长上升子序列的长度
序列初始时为空.
n<=500000且所有输入的数字都是长整型范围内的非负整数

题解:

显然可以离散一下数字直接套用可持久化线段树,区间查询,单点修改。
也可以设fi表示长度为i的最小结尾,接着强行可持久化线段树,线段树上二分,单点修改。

但是空间都会炸~~空间限制是64MB。

所以比赛时我只有80points,数据结构学傻了,想不到其它做法,于是AK梦被毁。

事实上可以把这个搞成一棵树。

然后重新按树的顺序做。

父亲和儿子节点直接的修改只有一个,所以强行暴力修改撤销即可。

空间复杂度O(n),时间复杂度O(n log n),且是二分的log,常数超级优美。

OJ卡栈,所以令人厌恶的人工栈又得上了。

Code:

#include<cstdio>#include<cstring>#define fo(i, x, y) for(int i = x; i <= y; i ++)#define min(a, b) ((a) < (b) ? (a) : (b))using namespace std;const int N = 5e5 + 5;int n, op[N], a[N], b[N];int next[N], to[N], final[N], tot;void link(int x, int y) {next[++ tot] = final[x], to[tot] = y, final[x] = tot;}int l, r, m, mx, ans, p[N][2], s[N], bz[N];int z0, zi[N], zx[N], zz[N];void dg(int x) {    z0 = 1; zz[z0] = 0; zx[z0] = x;    while(z0) {        if(zz[z0] == 0) {            int pb = 1; x = zx[z0];            s[x] = mx;            for(int i = final[x]; i; i = next[i]) {                if(op[to[i]] == 0) {                    ans = 0;                    for(l = 1, r = mx; l <= r;) {                        m = l + r >> 1;                        if(b[m] < a[to[i]]) ans = m, l = m + 1; else r = m - 1;                    }                    ans ++;                    p[x][0] = ans; p[x][1] = b[ans];                    if(ans > mx) mx ++, bz[x] = 1; else bz[x] = 0;                    b[ans] = min(b[ans], a[to[i]]);                    zi[z0] = i; zx[z0] = x; zz[z0] = 1;                    zx[++ z0] = to[i], zz[z0] = 0; pb = 0; break;                    b[p[x][0]] = p[x][1]; mx -= bz[x];                } else {                    zi[z0] = i; zx[z0] = x; zz[z0] = 1;                    zx[++ z0] = to[i], zz[z0] = 0; pb = 0; break;                }            }            z0 -= pb;        } else {            int pb = 1; x = zx[z0];            b[p[x][0]] = p[x][1]; mx -= bz[x];            for(int i = next[zi[z0]]; i; i = next[i]) {                if(op[to[i]] == 0) {                    ans = 0;                    for(l = 1, r = mx; l <= r;) {                        m = l + r >> 1;                        if(b[m] < a[to[i]]) ans = m, l = m + 1; else r = m - 1;                    }                    ans ++;                    p[x][0] = ans; p[x][1] = b[ans];                    if(ans > mx) mx ++, bz[x] = 1; else bz[x] = 0;                    b[ans] = min(b[ans], a[to[i]]);                    zi[z0] = i; zx[z0] = x; zz[z0] = 1;                    zx[++ z0] = to[i], zz[z0] = 0; pb = 0; break;                } else {                    zi[z0] = i; zx[z0] = x; zz[z0] = 1;                    zx[++ z0] = to[i], zz[z0] = 0; pb = 0; break;                }            }            z0 -= pb;        }    }}int main() {    freopen("lis.in", "r", stdin);    freopen("lis.out", "w", stdout);    scanf("%d", &n);    fo(i, 1, n) {        scanf("%d %d", &op[i], &a[i]);        if(op[i] == 0) link(i - 1, i); else link(a[i], i);    }    fo(i, 1, n) b[i] = 2147483647;    dg(0);    fo(i, 1, n) printf("%d\n", s[i]);}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信限制加好友怎么办 珍爱网的客服老打电话怎么办 百合网的人气是怎么办 苹果x来电不显示怎么办 苹果8黑屏没反应怎么办 苹果六s开不了机怎么办 苹果6s突然黑屏怎么办 苹果6s黑屏了怎么办 苹果6s手机黑屏打不开怎么办 苹果6sp手机死机怎么办 苹果6s打不开机怎么办 6s开不了机怎么办 lg背光灯坏了怎么办 苹果6s屏幕变黄怎么办 苹果8背光坏了怎么办 苹果六背光坏了怎么办 苹果5s蓝屏死机怎么办 苹果6s突然黑屏怎么办? 苹果6s经常死机怎么办 苹果6s没有背光怎么办 苹果7白屏死机怎么办 苹果6p屏膜失灵怎么办 苹果7p屏幕卡死怎么办 苹果7p手机死机怎么办 苹果6s死机了怎么办啊 6s死机了关不了怎么办 爱疯7死机了怎么办 苹果11.4系统老死机怎么办 苹果6震动坏了怎么办 苹果6手机死机了怎么办 苹果x耗电太快怎么办 苹果6升级11.3卡怎么办 苹果6splus耗电快怎么办 苹果手机系统升级后反应慢怎么办 苹果8听筒声音小怎么办 苹果6s通话声音小怎么办 苹果手机通讯录丢失了怎么办 苹果换id通讯录没有了怎么办 华为p7 更新重启怎么办 打电话的图标没了怎么办 苹果手机wifi信号弱怎么办