BZOJ 3207: 花神的嘲讽计划Ⅰ

Description

背景
花神是神,一大癖好就是嘲讽大J,举例如下:
“哎你傻不傻的!【hqz:大笨J】”
“这道题又被J屎过了!!”
“J这程序怎么跑这么快!J要逆袭了!”
……
描述
这一天DJ在给吾等众蒟蒻讲题,花神在一边做题无聊,就跑到了一边跟吾等众蒟蒻一起听。以下是部分摘录:
1.
“J你在讲什么!”
“我在讲XXX!”
“哎你傻不傻的!这么麻烦,直接XXX再XXX就好了!”
“……”
2.
“J你XXX讲过了没?”
“……”
“那个都不讲你就讲这个了?哎你傻不傻的!”
“……”
DJ对这种情景表示非常无语,每每出现这种情况,DJ都是非常尴尬的。
经过众蒟蒻研究,DJ在讲课之前会有一个长度为N方案,我们可以把它看作一个数列;
同样,花神在听课之前也会有一个嘲讽方案,有M个,每次会在x到y的这段时间开始嘲讽,为了减少题目难度,每次嘲讽方案的长度是一定的,为K。
花神嘲讽DJ让DJ尴尬需要的条件:
在x~y的时间内DJ没有讲到花神的嘲讽方案,即J的讲课方案中的x~y没有花神的嘲讽方案【这样花神会嘲讽J不会所以不讲】。
经过众蒟蒻努力,在一次讲课之前得到了花神嘲讽的各次方案,DJ得知了这个消息以后欣喜不已,DJ想知道花神的每次嘲讽是否会让DJ尴尬【说不出话来】。

Input

第1行3个数N,M,K;
第2行N个数,意义如上;
第3行到第3+M-1行,每行K+2个数,前两个数为x,y,然后K个数,意义如上;

Output

对于每一个嘲讽做出一个回答会尴尬输出‘Yes’,否则输出‘No’

Sample Input

8 5 3
1 2 3 4 5 6 7 8
2 5 2 3 4
1 8 3 2 1
5 7 4 5 6
2 5 1 2 3
1 7 3 4 5

Sample Output

No
Yes
Yes
Yes
No

HINT

题中所有数据不超过2*10^9;保证方案序列的每个数字<=N
2~5中有2 3 4的方案,输出No,表示DJ不会尴尬
1~8中没有3 2 1的方案,输出Yes,表示DJ会尴尬
5~7中没有4 5 6的方案,输出Yes,表示DJ会尴尬
2~5中没有1 2 3的方案,输出Yes,表示DJ会尴尬
1~7中有3 4 5的方案,输出No,表示DJ不会尴尬

Source

原创 Memphis

Solution

哈希+离散化+可持久化线段树

把序列当做字符串,每K个字符取次Hash,离散化后存到主席树里。对于每次询问,求出询问序列的哈希,在主席树中找出现次数即可。

Code

#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
typedef unsigned long long ULL;
const int INF = 1009999999;
const int maxn = 100005;
const int maxlog = 25;
const ULL Base = 100207ULL;
int getint() {
    int r = 0, k = 1; char c = getchar();
    for (; '0' > c || c > '9'; c = getchar()) if (c == '-') k = -1;
    for (; '0' <= c && c <= '9'; c = getchar()) r = r * 10 - '0' + c;
    return r * k;
}
map<int, int> M;
int tot, lc[maxn * maxlog], rc[maxn * maxlog], val[maxn * maxlog], n, m, k, cnt, root[maxn], l, r, Mag, HSK;
ULL H[maxn], H2[maxn], T[maxn], Has;
ULL GetHash(int l, int r) {
    return H[r] - H[l-1] * T[r - l + 1];
}
void Change(int &x, int y, int l, int r, int pos) {
    x = ++tot;
    lc[x] = lc[y];
    rc[x] = rc[y];
    if (l == r) return (void)(val[x] = val[y] + 1);
    int mid = (l + r) >> 1;
    if (pos <= mid) return Change(lc[x], lc[y], l, mid, pos);
    else return Change(rc[x], rc[y], mid+1, r, pos);
}
int Query(int x, int y, int l, int r, int pos) {
    if (l == r) return val[x] - val[y];
    int mid = (l + r) >> 1;
    if (pos <= mid) return Query(lc[x], lc[y], l, mid, pos);
    else return Query(rc[x], rc[y], mid+1, r, pos);
}
int main() {
    n = getint(); m = getint(); k = getint();
    T[0] = 1ULL; for (int i = 1; i <= n; ++i) T[i] = T[i-1] * Base;
    if (k == 0) for (int i = 1; i <= m; ++i) puts("No");
    else {
        for (int i = 1; i <= n; ++i)
            H[i] = H[i-1] * Base + getint();
        for (int i = k; i <= n; ++i) {
            H2[i] = GetHash(i - k + 1, i);
            M[H2[i]] = 0;
        }
        for (map<int, int>::iterator it = M.begin(); it != M.end(); ++it)
            it->second = ++cnt;
        for (int i = k; i <= n; ++i)
            Change(root[i], root[i-1], 1, n, M[H2[i]]);
        while (m--) {
            l = getint() + k - 1; r = getint();
            if (l > r) puts("Yes");
            else {
                Has = 0;
                for (int i = 1; i <= k; ++i) Has = Has * Base + getint();
                if (M.find(Has) == M.end()) puts("Yes");
                else {
                    Has = M[Has];
                    if (Query(root[r], root[l-1], 1, n, Has) > 0) puts("No");
                    else puts("Yes");
                }
            }
        }
    }
}

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据