@Falsyta
2015-08-09T05:11:25.000000Z
字数 6302
阅读 1394
OI
mxh带窝飞
对于两个字符串
对于两个字符串
mxh Round www
给出两个串
给出
有
对于给定的无向图
维护一个多重集
1. 向
2. 删除最小元素
3. 询问最大元素
给出长度为
求
其中
令
求
考虑对每个串
显然地,对于
在SAM上DP即可。
别忘了unsigned long long QAQ
# include <cstdio>
# include <cstring>
# define REP(i, n) for (int i = 1; i <= n; i ++)
# define REP_0(i, n) for (int i = 0; i < n; i ++)
# define REP_0N(i, n) for (int i = 0; i <= n; i ++)
# define REP_D(i, n) for (int i = n; i >= 1; i --)
# define CLR(a, x) memset (a, x, sizeof (a))
typedef unsigned long long ll;
const int NR = 100100;
struct Sam {int trans[26], par, l; Sam () {CLR (trans, -1);}} sam[NR << 1];
int d[NR << 1], cnt[NR], lst, sz, q0;
ll f[NR << 1], g[NR << 1], res[30];
char s0[NR], s1[NR];
# define u sam[x]
# define v u.trans[c]
# define vn sam[v]
# define o sam[y]
# define w sam[z]
inline void Init () {REP (x, sz) CLR (u.trans, -1); sam[sz = lst = 1].par = -1;}
void AddChar (int c)
{
int x = lst, z = ++ sz; lst = z, w.l = u.l + 1;
for (; x != -1 && v == -1; x = u.par) v = z;
if (x == -1) w.par = 1;
else if (u.l + 1 == vn.l) w.par = v;
else
{
int y = ++ sz, tv = v;
o = vn, o.l = u.l + 1, w.par = vn.par = y;
for (; x != -1 && v == tv; x = u.par) v = y;
}
}
void Sort (int len)
{
REP_0N (i, len) cnt[i] = 0;
REP (x, sz) cnt[u.l] ++;
REP (i, len) cnt[i] += cnt[i - 1];
REP (x, sz) d[cnt[u.l] --] = x;
}
int main ()
{
for (scanf ("%d", &q0); q0; q0 --)
{
scanf ("%s%s", s0 + 1, s1 + 1);
int l0 = strlen (s0 + 1), l1 = strlen (s1 + 1);
Init (); REP (i, l1) AddChar (s1[i] - 'a'); Sort (l1);
REP_D (i, sz)
{
int x = d[i]; g[x] = 1;
REP_0 (c, 26) if (v != -1) g[x] += g[v];
}
{int x = 1; REP_0 (c, 26) v != -1 ? res[c] = g[v] : res[c] = 0;}
Init (); REP (i, l0) AddChar (s0[i] - 'a'); Sort (l0);
REP (x, sz) f[x] = (u.par == -1 ? 1 : (u.l - sam[u.par].l));
REP_D (i, sz)
{
int x = d[i];
REP_0 (c, 26) if (v == -1) f[x] += res[c] * (u.par == -1 ? 1 : (u.l - sam[u.par].l));
if (u.par != -1) f[u.par] += f[x];
}
printf ("%llu\n", f[1]);
}
return 0;
}
注意到
# include <cstdio>
int main ()
{
int q0, n, m, z, l;
for (scanf ("%d", &q0); q0; q0 --)
{
scanf ("%d%d%d%d", &n, &m, &z, &l);
int res = 0, a = 0;
for (int i = 2; i <= n; i ++) a = (1ll * a * m + z) % l, res ^= (a << 1);
printf ("%d\n", res);
}
return 0;
}
考虑编号从小到大染灰。
令
考虑一个环,做法是显然的。
把所有环删掉以后原图变为森林。
在树上DFS一遍显然可以定向。
# include <cstdio>
# include <cstring>
# include <cassert>
# include <algorithm>
# include <iostream>
# define REP(i, n) for (int i = 1; i <= n; i ++)
# define REP_G(i, x) for (int i = pos[x]; i; i = g[i].f)
# define RST(a) memset (a, 0, sizeof (a))
using namespace std;
const int NR = 100100, ER = 300100;
int q0, n, m, gsz, top, f[NR], pos[NR], stk[NR], cur[NR], pre[NR];
bool vis[NR], col[ER], del[ER];
struct Edge {int y, f; void Set (int yr, int fr) {y = yr, f = fr;}} g[ER << 1];
void AE (int x, int y) {g[++ gsz].Set (y, pos[x]), pos[x] = gsz;}
# define v g[i].y
void DFS (int S)
{
vis[stk[top = 1] = S] = 1;
while (top)
{
int x = stk[top]; bool EXIT = 0;
for (int &i = cur[x]; i; i = g[i].f)
{
if ((pre[x] ^ 1) == i || del[i >> 1]) continue;
if (vis[v])
{
del[i >> 1] = 1, col[i >> 1] = (i & 1);
for (; stk[top] != v; top --) del[pre[stk[top]] >> 1] = 1, col[pre[stk[top]] >> 1] = (pre[stk[top]] & 1), vis[stk[top]] = 0;
i = g[i].f;
EXIT = 1; break;
}
else {vis[stk[++ top] = v] = 1; pre[v] = i, i = g[i].f; EXIT = 1; break;}
}
if (!EXIT) vis[x] = 0, top --;
}
}
void Calc (int x)
{
vis[x] = 1;
REP_G (i, x)
if (!vis[v] && !del[i >> 1])
{
if (!f[x]) f[x] = 1, f[v] = -1, col[i >> 1] = (i & 1), Calc (v);
else col[i >> 1] = ((f[x] == 1) ^ (i & 1)), f[v] = f[x], f[x] = 0, Calc (v);
}
}
int main ()
{
for (scanf ("%d", &q0); q0; q0 --)
{
scanf ("%d%d", &n, &m), gsz = 1; int t1, t2;
RST (f), RST (col), RST (vis), RST (del), RST (pos);
REP (i, m)
{
scanf ("%d%d", &t1, &t2);
if (t1 == t2) gsz += 2;
else AE (t1, t2), AE (t2, t1);
}
REP (i, n) cur[i] = pos[i];
REP (i, n) DFS (i);
REP (i, n) if (!vis[i]) Calc (i);
REP (i, m) printf ("%d\n", col[i]);
}
return 0;
}
维护最大值和当前集合大小。
考虑题目和哈夫曼树有关。
原函数的意义是添加到位置
用哈夫曼树求得的解显然是最优的。
# include <cstdio>
# include <queue>
# define REP(i, n) for (int i = 1; i <= n; i ++)
using namespace std;
priority_queue <long long> Q;
int main ()
{
int q0;
for (scanf ("%d", &q0); q0; q0 --)
{
int ta, n;
scanf ("%d", &n);
REP (i, n) scanf ("%d", &ta), Q.push (- ta);
long long ans = 0;
while (1)
{
int w0 = - Q.top (), w1; Q.pop ();
if (Q.empty ()) break;
w1 = - Q.top (); Q.pop ();
ans += w0 + w1, Q.push (- w0 - w1);
}
printf ("%I64d\n", ans);
}
return 0;
}
打表,不会证。
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <iostream>
# define REP(i, n) for (int i = 1; i <= n; i ++)
# define REP_0(i, n) for (int i = 0; i < n; i ++)
# define REP_D0(i, n) for (int i = n - 1; i >= 0; i --)
# define FOR(i, a, b) for (int i = a; i <= b; i ++)
# define RST(a) memset (a, 0, sizeof (a))
using namespace std;
const int NR = 10000;
const int P = 258280327;
const int W = 100000000;
int poolA[NR], la, poolB[NR], lb, poolC[NR], lc;
int f[20000];
bool Comp (int *a, int *b, int la, int lb)
{
if (la > lb) return 1;
if (la < lb) return 0;
REP_D0 (i, la)
{
if (a[i] > b[i]) return 1;
if (a[i] < b[i]) return 0;
}
return 0;
}
void Minus (int *a, int *b, int &la, int lb)
{
REP_0 (i, lb)
{
a[i] -= b[i];
if (a[i] < 0)
{
a[i] += W, a[i + 1] --;
if (i + 1 == lb) lb ++;
}
}
if (la == lb) while (!a[la - 1]) la --;
}
void Add (int *a, int *b, int &la, int lb)
{
REP_0 (i, lb)
{
a[i] += b[i];
if (a[i] >= W)
{
a[i] -= W, a[i + 1] ++;
if (i + 1 == lb) lb ++;
}
}
if (lb > la) la = lb;
}
char s[2000];
int main ()
{
int q0, n; f[0] = 0, f[1] = 1;
FOR (i, 2, 15000)
{
f[i] = f[i - 1] + f[i - 2];
if (f[i] >= P) f[i] -= P;
}
for (scanf ("%d", &q0); q0; q0 --)
{
scanf ("%d%s", &n, s), RST (poolA), RST (poolB), RST (poolC);
int len = strlen (s);
REP_0 (i, len) if (i < len - i - 1) swap (s[len - i - 1], s[i]);
if (n < 3) {printf ("%d\n", 0); continue;}
la = lb = lc = 0;
int *a = poolA, *b = poolB, *c = poolC, tW = 0;
REP_D0 (i, len)
{
tW = 1ll * tW * 10 + s[i] - '0';
if (!(i % 8)) a[la ++] = tW, tW = 0;
}
REP_0 (i, la) if (i < la - i - 1) swap (a[la - i - 1], a[i]);
int cur = 0, lev = 0, aw = 0;
lb = lc = b[0] = c[0] = 1;
while (Comp (a, b, la, lb))
{
Minus (a, b, la, lb), Add (c, b, lc, lb);
swap (b, c), swap (lb, lc);
cur += f[lev ++]; if (cur >= P) cur -= P;
}
REP_D0 (i, la) aw = (1ll * W * aw + a[i]) % P;
cur += aw - 1; if (cur >= P) cur -= P;
printf ("%d\n", cur);
}
return 0;
}