省选模拟赛[HEOI2012] Day2

比赛过程

7:30 am

  又是HEOI2012? 上次才考过Day1的. 浏览了一遍题… t2不是那个sb题吗??? wys昨晚才写了我没选择去看hh. 但是解法显然fail树上lca呵呵. 看一下t1, t3. t1又是数学? t3感觉像是搜索. 先想一下这两道吧.

8:30 am

  woc第一题样例260我怎么算不出来??不是5 * 4 * 4 * 4的320吗?260还是13的倍数? 13是怎么来的? 难不成不是普通的相乘还要有加法? 想了半天再看看那个图觉得没有问题. 抱着一股怨气去看了t3. 怎么我又看不懂题?? 不是每次只能往一个方向走吗? 我怎么知道他要选哪条? 还问我第i天他能走多少? 我怎么知道??? 至此我已经严重怀疑出题人的语文水平…好歹我停课了语文也进过年级前十的好吧. 弃了弃了. 先去码第二题吧.

9:30 am

  t2半个多小时就码出来了… 调了几下过了样例. 看一下t1, 我试着每个单位横着放像====这样的形式算一下– woc就是260? md为什么题面的图是||||这样的啊, 如果这样限制关系就少了. 推了一下式子发现可以nlogm的做, 先敲个暴力拿25pts算了. 再去看看第三题.

10:30 am

  woc我要给出题人寄刀片!!!. 还是读不懂t3啊QAQ. 算了时间不多还是再在t1找点部分分. 突然发现t1最后一个点p只有3000? 这不就有循环节然后是个等比数列求和? 发现没有逆元只能矩阵快速幂求和gg… 这玩意还没敲过… 不过还有一个小时慢慢来吧.

11:30am

  写完再复查了t2, 考试结束.

赛后

  怎么只有25分??? QAQ第二题文件好像又交错… 重交的时候现在bzoj上交了一下, 发现最后几个点要mle, 精准算了一下空间, 重交就A了. 唉算了这次就当考起耍吧, t1矩阵快速幂好像还是写挂了… 上次欢乐AK这次就惨痛爆零啊… 以后文件再交错我就直播吃翔. 不过qjx他们题也没读懂… 看来不是我的问题嘛233. 不过到我省选的时候要是读不懂题就是要崩溃了.

暂时只有t2的代码啦.

#include<bits/stdc++.h>
using namespace std;
const int P = 20;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 5;
queue<int> q;
char str[maxn];
int num, tot, sz, n, m;
int c[maxn][26], fail[maxn << 1];
int anc[maxn][P + 1], ans[maxn], dep[maxn << 1];
int bin[maxn << 1], id[maxn << 1], bef[maxn << 1];
inline void init() {
    bin[0] = 1;
    for (int i = 1; i <= 20; ++ i)
        bin[i] = bin[i - 1] << 1;
}
inline void insert(char *ss) {
    int p = 0;
    for (int i = 0; ss[i]; ++ i) {
        int index = ss[i] - 'a';
        if (!c[p][index]) {
            c[p][index] = ++ tot;
            ans[tot] = (1ll * index + 1ll * ans[p] * 26) % mod;
        }
        p = c[p][index];
        id[++ sz] = p;
    }
}
inline void getfail() {
    for (int i = 0; i < 26; ++ i)
        if (c[0][i]) q.push(c[0][i]), dep[c[0][i]] = 1;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int i = 1; i < P && dep[u] >= bin[i]; ++ i)
            anc[u][i] = anc[anc[u][i - 1]][i - 1];
        for (int i = 0; i < 26; ++ i) {
            if (c[u][i]) {
                fail[c[u][i]] = c[fail[u]][i];
                anc[c[u][i]][0] = fail[c[u][i]];
                dep[c[u][i]] = dep[fail[c[u][i]]] + 1, q.push(c[u][i]);
            } else c[u][i] = c[fail[u]][i];
        }
    }
}
inline int query(int u, int v) {
    if (dep[u] < dep[v]) swap(u, v);
    int t = dep[u] - dep[v];
    for (int i = 0; i < P; ++ i)
        if (t & bin[i]) u = anc[u][i];
    for (int i = P - 1; ~i; -- i)
        if (anc[u][i] != anc[v][i])
            u = anc[u][i], v = anc[v][i];
    return (u == v) ? u : anc[u][0];
}
int main() {
    init();
    scanf("%d", &n);
    for (int i = 1; i <= n; ++ i)
        bef[i] = sz, scanf("%s", str), insert(str);
    getfail();
    scanf("%d", &m);
    for (int i = 1; i <= m; ++ i) {
        int x, y, k, l;
        scanf("%d%d%d%d", &x, &y, &k, &l);
        x = id[bef[x] + y], k = id[bef[k] + l];
        printf("%d\n", ans[query(x, k)]);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值