2 条题解

  • 0
    @ 2026-6-11 21:38:40

    也可以不转换将翻译方向:只要不超过一圈,每次都贪心地向前翻译到语义差距尽量大的单词显然是最优的。

    考虑断环成链后分块,逐步将单词环重复一遍拼接在链末,一边拼接一边求解。对每个元素维护它跳出当前块的翻译次数和落点,在每个单词出现在链末时求解答案,这样就不会超过一圈了。

    最终的时间复杂度为 O(Tnn)O(Tn \sqrt n),空间复杂度为 O(n)O(n),进一步用 LCT 替换分块可以做到 O(Tnlog⁡n)O(Tn \log n) 的优秀时间复杂度。

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 100005;
    int nxt[MAXN], jmp[MAXN], stp[MAXN]; int tag[MAXN];
    int blk[MAXN], bl[MAXN], br[MAXN];
    void rebuild(int x) {
    	for (int i = br[x]; i >= bl[x]; i--) {
    		if (nxt[i] < i || nxt[i] > br[x]) jmp[i] = nxt[i], stp[i] = 1;
    		else jmp[i] = jmp[nxt[i]], stp[i] = stp[nxt[i]] + 1;
    	}
    }
    void pushdown(int x) {
    	if (tag[x] != -1) {
    		for (int i = bl[x]; i <= br[x]; i++) nxt[i] = tag[x];
    		tag[x] = -1; rebuild(x);
    	}
    }
    int a[MAXN], lat[MAXN], buc[MAXN];
    namespace sgt {
    	int f[MAXN << 2];
    	void build(int rt, int l, int r) {
    		f[rt] = -1; if (l == r) return; int mid = (l + r) >> 1;
    		build(rt << 1, l, mid); build(rt << 1 | 1, mid + 1, r);
    	}
    	void modify(int rt, int l, int r, int x, int y, int w) {
    		if (x > y) return; if (x <= l && r <= y) return f[rt] = max(f[rt], w), void();
    		int mid = (l + r) >> 1;
    		if (x <= mid) modify(rt << 1, l, mid, x, y, w);
    		if (y > mid) modify(rt << 1 | 1, mid + 1, r, x, y, w);
    	}
    	void push(int rt, int l, int r) {
    		if (l == r) return nxt[l] = f[rt], void(); int mid = (l + r) >> 1;
    		f[rt << 1] = max(f[rt << 1], f[rt]);
    		f[rt << 1 | 1] = max(f[rt << 1 | 1], f[rt]);
    		push(rt << 1, l, mid); push(rt << 1 | 1, mid + 1, r);
    	}
    }
    int main() {
    	freopen("translation.in", "r", stdin); freopen("translation.out", "w", stdout);
    	int t; scanf("%d", &t); while (t--) {
    		int n; scanf("%d", &n);
    		int b = sqrt(n);
    		int nb = (n + b - 1) / b;
    		for (int i = 1; i <= n; i++) tag[i] = -1;
    		for (int i = 1; i <= nb; i++) {
    			bl[i] = b * (i - 1) + 1; br[i] = min(b * i, n);
    			for (int _ = bl[i]; _ <= br[i]; _++) blk[_] = i;
    			rebuild(i);
    		}
    		for (int i = 1; i <= n; i++) scanf("%d", &a[i]), buc[a[i]] = i;
    		for (int i = 1; i <= n; i++) lat[i] = buc[a[i]], buc[a[i]] = i;
    
    		sgt::build(1, 1, n);
    		for (int i = 2; i <= n; i++) {
    			int p = lat[i] >= i ? n : lat[i];
    			p = p % n + 1;
    			sgt::modify(1, 1, n, p, i - 1, i);
    		}
    		sgt::push(1, 1, n);
    		for (int i = 1; i <= nb; i++) rebuild(i);
    
    		for (int i = 1; i <= n; i++) {
    			int tmp = tag[blk[i]] != -1 ? tag[blk[i]] : nxt[i];
    			int j = lat[i]; j = j % n + 1;
    			if (j < i) {
    				int bi = blk[i], bj = blk[j];
    				if (bi == bj) {
    					pushdown(bi); for (int _ = j; _ < i; _++) nxt[_] = i;
    					nxt[i] = -1; rebuild(bi);
    				}
    				else {
    					pushdown(bi); pushdown(bj);
    					for (int _ = j; _ <= br[bj]; _++) nxt[_] = i;
    					for (int _ = bj + 1; _ < bi; _++) tag[_] = i;
    					for (int _ = bl[bi]; _ < i; _++) nxt[_] = i;
    					nxt[i] = -1; rebuild(bi); rebuild(bj);
    				}
    			}
    			else {
    				int bi = blk[i], bj = blk[j];
    				if (bi == bj) {
    					pushdown(bi);
    					for (int _ = j; _ <= br[bj]; _++) nxt[_] = i;
    					for (int _ = bj + 1; _ <= nb; _++) tag[_] = i;
    					for (int _ = 1; _ < bi; _++) tag[_] = i;
    					for (int _ = bl[bi]; _ < i; _++) nxt[_] = i;
    					nxt[i] = -1; rebuild(bi);
    				}
    				else {
    					pushdown(bi); pushdown(bj);
    					for (int _ = j; _ <= br[bj]; _++) nxt[_] = i;
    					for (int _ = bj + 1; _ <= nb; _++) tag[_] = i;
    					for (int _ = 1; _ < bi; _++) tag[_] = i;
    					for (int _ = bl[bi]; _ < i; _++) nxt[_] = i;
    					nxt[i] = -1; rebuild(bi); rebuild(bj);
    				}
    			}
    			int step = 0;
    			while (tmp != -1) {
    				if (tag[blk[tmp]] != -1) step++, tmp = tag[blk[tmp]];
    				else step += stp[tmp], tmp = jmp[tmp];
    			}
    			printf("%d%c", step, " \n"[i == n]);
    		}
    	}
    }
    

    信息

    ID
    199
    时间
    4000ms
    内存
    512MiB
    难度
    7
    标签
    递交数
    58
    已通过
    4
    上传者