省选测试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