省选测试49

A 进攻! (Unaccepted)

题目大意 :

Code

Show Code

B 字符串

  • 把n个字符串连起来,把询问放到字符串上,然后就可以莫队了,有set维护G集合,时间复杂度\(n\sqrt n \log n\)

Code

Show Code
#include <set>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long ll;
const int N = 3e5 + 5, SZ = 3000;

int read(int x = 0, int f = 1, char c = getchar()) {
    for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
    for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
    return x * f;
}

char c[N];
ll s[N], sum, mx, ans[N];
int n, m, A, B, C, w[N], a[N], g[N], ch[N][26], trc, cnt, pos[N], R[N], ml, len[N], v[N], b[N];
set<int> S;
set<int>::iterator it;

void Insert(int w) {
    int p = 0;
    for (int i = 1; c[i]; ++i) {
        int k = c[i] - 'a';
        if (!ch[p][k]) ch[p][k] = ++trc;
        p = ch[p][k]; 
        pos[++cnt] = p; a[cnt] = w; len[cnt] = i;
    }
}

struct Ques {
    int l, r, id;
}q[N];

bool operator < (const Ques &a, const Ques &b) {
    int c1 = (a.l - 1) / SZ + 1, c2 = (b.l - 1) / SZ + 1;
    return c1 != c2 ? c1 < c2 : c1 & 1 ? a.r < b.r : a.r > b.r;
}

ll Gcd(ll a, ll b) {
    return b ? Gcd(b, a % b) : a;
}

void Add(int x) {
    int y = pos[x]; ll tmp = s[y]; 
    s[y] += 1ll * a[x] * B + (!b[y]++ ? 1ll * A * len[x] : 0ll);
    if (tmp < C && s[y] >= C && !v[len[x]]++) {
        x = g[len[x]];
        it = S.lower_bound(x);
        int nt = *it, lt = *--it; 
        S.insert(x);
        sum -= 1ll * (x - lt) * (nt - x);
    }
}

void Del(int x) {
    int y = pos[x]; ll tmp = s[y]; 
    s[y] -= 1ll * a[x] * B + (!--b[y] ? 1ll * A * len[x] : 0ll);
    if (tmp >= C && s[y] < C && !--v[len[x]]) {
        x = g[len[x]]; S.erase(x);
        it = S.lower_bound(x);
        int nt = *it, lt = *--it; 
        sum += 1ll * (x - lt) * (nt - x);
    }
}

int main() {
    freopen("string.in", "r", stdin);
    freopen("string.out", "w", stdout);
    n = read(); A = read(); B = read(); C = read();
    for (int i = 1; i <= n; ++i) w[i] = read();
    for (int i = 1; i <= n; ++i) {
        scanf("%s", c + 1); 
        Insert(w[i]); R[i] = cnt; 
        ml = max(ml, (int)strlen(c + 1));
    }
    for (int i = 1; i <= ml; ++i) g[i] = read();
    m = read(); mx = 1ll * (ml + 1) * ml / 2;
    for (int i = 1; i <= m; ++i)
        q[i] = (Ques) {R[read()-1]+1, R[read()], i};
    sort(q + 1, q + m + 1);
    int l = 1, r = 0; sum = mx;
    S.insert(0), S.insert(ml + 1);
    for (int i = 1; i <= m; ++i) {
        while (l > q[i].l) Add(--l);
        while (r < q[i].r) Add(++r);
        while (l < q[i].l) Del(l++);
        while (r > q[i].r) Del(r--);
        ans[q[i].id] = sum;
    }
    for (int i = 1; i <= m; ++i) {
        ans[i] = mx - ans[i];
        ll g = Gcd(ans[i], mx);
        printf("%lld/%lld\n", ans[i]/g, mx/g);
    }
    return 0;
}

C 序列 (Unaccepted)

题目大意 :

Code

Show Code
posted @ 2021-03-28 15:19  Shawk  阅读(52)  评论(0编辑  收藏  举报