-如非必要，不用STL-患者红小豆上线

HDU-6592 Beauty of  unimodal sequence

调完了诸如中括号里打了另一个数组的下标之类的bug之后，最大的wa点是dp数组大小少打个0

const xx maxn 一个错全都错，还是每个数组打一次大小 一个错错一个，这是一个问题_(:з」∠)_

输出格式好要命啊啊啊wa之后还来了发PE

正文：首先对序列正着跑一边LIS，再反着跑一遍，分别记录下标（ppo-positive，opo-over：P）顺便给po初始化一下；

原blog开了两个vector，小可寻思着一个数组（叫v吧）加个下标变量就可以复用。

细节见码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
using namespace std;
typedef long long LL;
int n;
int num[300005], ppo[300005], opo[300005], v[300005], d[300005], po[300005];
stack<int>sa;

int main()
{
while (~scanf("%d", &n)) {

memset(d, 0x3f, sizeof d);
d[0] = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", &num[i]);
ppo[i] = lower_bound(d + 1, d + 1 + n, num[i]) - d;
d[ppo[i]] = num[i];
po[i] = 0x3f3f3f3f;
}
memset(d, 0x3f, sizeof d);
d[0] = 0;
for (int i = n; i >= 1; i--) {
opo[i] = lower_bound(d + 1, d + 1 + n, num[i]) - d;
d[opo[i]] = num[i];
}

int co = 0;
int now = 1, m = ppo[1] + opo[1];
for (int i = 2; i <= n; i++)
if (ppo[i] + opo[i] > m) { now = i; m = opo[i] + ppo[i]; }
po[ppo[now]] = num[now];
for (int i = now - 1; i >= 1; i--) {
if (po[ppo[i] + 1] <= num[i]) continue;
while (!sa.empty() && ppo[i] >= ppo[sa.top()])po[ppo[sa.top()]] = 0x3f3f3f3f, sa.pop();
sa.push(i);
po[ppo[i]] = num[i];
}
while (!sa.empty()) v[co++] = sa.top(), sa.pop();
v[co++] = now;
for (int i = now + 1; i <= n; i++)
if (opo[i] == opo[v[co - 1]] - 1 && num[i] < num[v[co - 1]])v[co++] = i;
for (int i = 0; i < co; i++)printf("%d%c", v[i], " \n"[i == co - 1]);

co = 0;
now = 1; m = ppo[1] + opo[1]; po[1] = 0x3f3f3f3f;
for (int i = 2; i <= n; i++) {
if (ppo[i] + opo[i] >= m) { now = i; m = opo[i] + ppo[i]; }
po[i] = 0x3f3f3f3f;
}
sa.push(now);
for (int i = now - 1; i >= 1; i--)
if (ppo[i] == ppo[sa.top()] - 1 && num[i] < num[sa.top()])sa.push(i);
while (!sa.empty())v[co++] = sa.top(), sa.pop();
po[opo[now]] = num[now];
for (int i = now + 1; i <= n; i++) {
if (num[i] >= po[opo[i] + 1]) continue;
while (co && opo[i] >= opo[v[co - 1]])po[opo[v[co - 1]]] = 0x3f3f3f3f, co--;
v[co++] = i;
po[opo[i]] = num[i];
}
for (int i = 0; i < co; i++)printf("%d%c", v[i], " \n"[i == co - 1]);
}

return 0;
}
Beauty of unimodal sequence

（新建之前想着还有什么要写来着但是忘了。。想起来再说）

upd：

HDU-6599 I Love Palindrome String

整个学习过程充满指针乱跳，终于是大概知道怎么用了，配上Thor的马拉车板子，开始乱搞。

大佬题解中非常神奇的部分是在回文树中自加的那个函数，将原回文串中的下标映射回马拉车得到的回文串的长度数组的下标，检查半个回文串的长度，判断是否符合条件

一开始各种T，学大佬加了一些inline和register之后又wa来wa去，检查了马拉车后来加的两个数组发现开小了_(:з」∠)_

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long LL;

const int MAXN = 300005;
const int N = 26;
int ans[MAXN], rlen[MAXN * 2];
char a[MAXN];
char  str[MAXN * 2];
int R[MAXN*2];

struct Palindromic_Tree {
int next[MAXN][N], fail[MAXN], cnt[MAXN], len[MAXN], S[MAXN], n, p, last;
int l[MAXN], r[MAXN];

inline int newnode(int l) {
for (register int i = 0; i < N; ++i) next[p][i] = 0;
cnt[p] = 0;
len[p] = l;
return p++;
}

void init() {
p = 0;
newnode(0);
newnode(-1);
last = 0;
n = 0;
S[n] = -1;
fail[0] = 1;
}

inline int get_fail(int x) {
while (S[n - len[x] - 1] != S[n]) x = fail[x];
return x;
}

c -= 'a';
S[++n] = c;
int cur = get_fail(last);

if (!next[cur][c]) {
int now = newnode(len[cur] + 2);
fail[now] = next[get_fail(fail[cur])][c];
next[cur][c] = now;
l[now] = n - len[cur] - 1;
r[now] = n;

}
last = next[cur][c];
cnt[last] ++;
}

void count() {
for (register int i = p - 1; i >= 0; --i) cnt[fail[i]] += cnt[i];
}

void map()
{
count();
for (int i = 2; i < p; i++) {

int ml = l[i] << 1, mmid = (l[i] + r[i]) >> 1 << 1;
int mid = (ml + mmid) >> 1;
if (mid - rlen[mid] + 1 <= ml)ans[len[i]] += cnt[i];
}
}

}pt;

void ma(int m)
{
memset(R, 0, sizeof(R));
int n = 0;
str[n++] = '!';
str[n++] = '#';
for (int i = 1; i <= m; i++)
str[n++] = a[i], str[n++] = '#';
str[n++] = '#';
str[n++] = '?';
int p = 0, mx = 0, ans = 0;
for (int i = 1; i < n; i++)
{
R[i] = mx > i ? min(R[2 * p - i], mx - i) : 1;
while (str[i + R[i]] == str[i - R[i]]) R[i]++;
if (R[i] + i > mx)
mx = i + R[p = i];
rlen[i] = R[i] - 1;
}
}

int main()
{

while (~scanf("%s", a + 1)) {
pt.init();
int l = strlen(a + 1);
for (int i = 1; i <= l; i++)pt.add(a[i]), ans[i] = 0;
ma(l);
pt.map();
for (int i = 1; i <= l; i++)printf("%d%c", ans[i], " \n"[i == l]);

}

return 0;
}
I Love Palindrome Strings

posted on 2019-08-04 17:28  Nonad  阅读(260)  评论(0编辑  收藏  举报