T1

0223模拟赛_c++

首先一个显然的性质是无环的竞赛图一定是一个全序集.

其次是如果钦定的点不是全序集那么必定无解.

无解判掉之后所有的点就被分成了两个全序集合(数据保证剩下的点无环). 我们枚举剩下的点看它能不能合法插入被钦定的全序集中. 对于能合法插入的点, 一定会有一个唯一的插入位置. 显然我们必须让这些点的插入位置递增(因为要满足两个全序关系). 于是我们按照全序顺序把所有能插入的点的插入位置求出来, 然后在上面求一个最长不降子序列就好了.

时间复杂度 O(n^2).

#include <bits/stdc++.h>
using namespace std;
template<class T>inline void read(T &x) {
char ch; while(!isdigit(ch=getchar()));
for(x=ch-'0'; isdigit(ch=getchar()); x=x*10+ch-'0');
}
const int MAXN = 2005;
int n, m, k, b[MAXN], c[MAXN], d[MAXN], seq[MAXN], f[MAXN];
bool a[MAXN][MAXN], flg[MAXN], suf[MAXN];
inline bool cmp(int i, int j) { return d[i] < d[j]; }
int main () {
freopen("circle.in", "r", stdin);
freopen("circle.out", "w", stdout);
read(n), read(k);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
read(a[i][j]);
for(int i = 1; i <= k; ++i) read(b[i]), flg[b[i]] = 1;
int cur = 0;
for(int i = 1; i <= n; ++i) if(!flg[i]) c[++cur] = i;

for(int i = 1; i <= k; ++i)
for(int j = i+1; j <= k; ++j)
d[b[j]] += a[b[i]][b[j]],
d[b[i]] += a[b[j]][b[i]];
for(int i = 1; i <= cur; ++i)
for(int j = i+1; j <= cur; ++j)
d[c[j]] += a[c[i]][c[j]],
d[c[i]] += a[c[j]][c[i]];

sort(b + 1, b + k + 1, cmp);
sort(c + 1, c + cur + 1, cmp);
bool chk = 1;
for(int i = 1; chk && i <= k; ++i)
for(int j = i+1; chk && j <= k; ++j)
if(a[b[j]][b[i]]) chk = 0;
//for(int i = 1; i <= k; ++i) printf("%d ", b[i]); puts("");
//for(int i = 1; i <= cur; ++i) printf("%d ", c[i]); puts("");
if(!chk) { puts("impossible"); return 0; };
for(int i = 1; i <= cur; ++i) {
suf[k+1] = 1;
for(int j = k; j >= 1; --j) suf[j] = suf[j+1]&(a[c[i]][b[j]]);
bool pre = 1; int pos = -1;
for(int j = 1; pre && j <= k+1; ++j) {
if(suf[j]) { pos = j; break; }
pre &= a[b[j]][c[i]];
}
if(~pos) seq[++m] = pos;
}
int ans = 0;
for(int i = 1; i <= m; ++i) {
int mx = 0;
for(int j = 1; j < i; ++j)
if(seq[i] >= seq[j]) mx = max(mx, f[j]);
ans = max(ans, f[i] = (mx + 1));
}
if(cur-ans >= k) puts("impossible");
else printf("%d\n", cur-ans);
}

T2

0223模拟赛_#include_02


0223模拟赛_#include_03


差分一下就可以维护。

0223模拟赛_c++_04

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 400005;
const int mod = 1e9 + 7;
char s[MAXN];
int n, m;

int len[MAXN], fail[MAXN], ch[MAXN][26], last = 1, tot = 1, pos[MAXN];
void ins(int c, int i) {
int p = last, np = ++tot;
len[last = pos[i] = np] = len[p] + 1;
while(p && !ch[p][c]) ch[p][c] = np, p = fail[p];
if(!p) { fail[np] = 1; return; }
int q = ch[p][c], nq;
if(len[q] == len[p] + 1) { fail[np] = q; return; }
len[nq = ++tot] = len[p] + 1; memcpy(ch[nq], ch[q], sizeof ch[q]), fail[nq] = fail[q];
fail[q] = fail[np] = nq;
while(p && ch[p][c] == q) ch[p][c] = nq, p = fail[p];
}
vector<int>e[MAXN];
int sz[MAXN], son[MAXN], top[MAXN], dfn[MAXN], seq[MAXN], tmr, fa[MAXN];
void dfs1(int u) {
sz[u] = 1;
for(int i = e[u].size()-1, v; i >= 0; --i) {
fa[v = e[u][i]] = u;
dfs1(v), sz[u] += sz[v];
if(sz[v] > sz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int tp) {
top[u] = tp; seq[dfn[u] = ++tmr] = u;
if(!son[u]) return;
dfs2(son[u], tp);
for(int i = e[u].size()-1, v; i >= 0; --i)
if((v=e[u][i]) != son[u]) dfs2(v, v);
}
inline void Add(int &x, int y) { x += y; x >= mod ? x -= mod : 0; }
inline int add(int x, int y) { return x + y >= mod ? x+y-mod : x+y; }
int upd[MAXN<<2], sum[MAXN<<2], lz[MAXN<<2];
void build(int i, int l, int r) {
if(l == r) { upd[i] = len[seq[l]] - len[fail[seq[l]]]; return; }
int mid = (l + r) >> 1;
build(i<<1, l, mid);
build(i<<1|1, mid+1, r);
upd[i] = add(upd[i<<1], upd[i<<1|1]);
}
void give(int i, int x) { Add(sum[i], 1ll*x*upd[i]%mod), Add(lz[i], x); }
void pd(int i) {
if(lz[i]) {
give(i<<1, lz[i]);
give(i<<1|1, lz[i]);
lz[i] = 0;
}
}
int query(int i, int l, int r, int x, int y) {
if(x <= l && r <= y) { int re = sum[i]; give(i, 1); return re; }
pd(i);
int mid = (l + r) >> 1, re = 0;
if(x <= mid) Add(re, query(i<<1, l, mid, x, y));
if(y > mid) Add(re, query(i<<1|1, mid+1, r, x, y));
sum[i] = add(sum[i<<1], sum[i<<1|1]);
return re;
}
int Query(int x) {
int re = 0;
while(x)
Add(re, query(1, 1, n, dfn[top[x]], dfn[x])), x = fa[top[x]];
return re;
}
int main () {
freopen("string.in", "r", stdin);
freopen("string.out", "w", stdout);
scanf("%d%s", &n, s+1);
for(int i = 1; i <= n; ++i) ins(s[i]-'a', i);
for(int i = tot; i > 1; --i) e[fail[i]].push_back(i);
dfs1(1); dfs2(1, 1);
m = n, n = tot;
build(1, 1, n);
int ans = 0, now = 0;
for(int i = 1; i <= m; ++i) {
Add(now, Query(pos[i]));
Add(ans, now);
printf("%d\n", ans);
}
}

T2

0223模拟赛_#include_05


0223模拟赛_#include_06

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 20000005;
int n, stk[MAXN], indx, a[MAXN];
char s[MAXN];
int main () {
freopen("simulate.in", "r", stdin);
freopen("simulate.out", "w", stdout);
scanf("%s", s+1); n = strlen(s+1);
for(int i = 1; i <= n; ++i) a[i] = s[i] - '0';
stk[++indx] = 0;
for(int i = 1; i <= n; ++i) {
s[i] = '1';
while(a[i] > 1) {
if(stk[indx] == i-1) a[i] -= 2, indx > 1 ? --indx : 1, ++a[i+1];
else if(!stk[indx]) stk[++indx] = 1, --a[i], ++a[i+1];
else {
int mov = min(i-1-stk[indx], a[i]-1);
stk[indx] += mov, a[i] -= mov, a[i+1] += mov;
}
}
if(!a[i]) stk[++indx] = i;
}
while(indx)s[stk[indx--]] = '0';
puts(s+1);
}