2025.8.28 Codeforces Round 1046 (Div. 1)
A. Against the Difference
题意
给一个序列,求其最长的可以分割成若干段 \([x,x,\dots,x]\)(\(x\) 个 \(x\))的子序列。
题解
预处理每个数的出现位置 \(p_{x,i}\),以及每个数是第几次出现的 \(o_i\)。dp 设 \(f(i)\) 为前 \(i\) 个数能取出的最长子序列,则
const int N = 2e5+5;
int n, a[N], o[N], f[N];
vector <int> p[N];
void solve(){
    cin >> n;
    for (int i=1; i<=n; ++i) p[i].clear();
    for (int i=1; i<=n; ++i)
    {
        cin >> a[i];
        p[a[i]].push_back(i);
        o[i] = p[a[i]].size();
    }
    for (int i=1; i<=n; ++i)
    {
        f[i] = f[i-1];
        if (o[i] >= a[i]) f[i] = max(f[i], f[p[a[i]][o[i] - a[i]] - 1] + a[i]);
    }
    cout << f[n] << '\n';
}
B. For the Champion
题意
交互题。已知 \(n\) 个点 \((x_i, y_i)\),你初始位于 \((X,Y)\)。
每次询问可以让自己向上下左右任意方向移动不超过 \(10^9\) 个单位,交互器会返回当前距离给定的 \(n\) 个点最近的曼哈顿距离 \(\min_{i=1}^n (|x-x_i| + |y-y_i|)\)。
最多 \(10\) 次询问,求 \(X,Y\) 的值。所有坐标均在 \([-10^9, 10^9]\) 之间。
题解
主要思路就是想办法把绝对值去掉。首先尽量往左下走:向左走 \(2\times 10^9\) 步,再向下走 \(2\times 10^9\) 步。这样就一定有 \(x<x_i, y<y_i\)。于是可以反推出 \(X+Y\)。
再尽量往右下走:在上面的基础上向右走 \(4\times 10^9\) 步。这样就一定有 \(x>x_i, y<y_i\),可以反推出 \(X-Y\)。
直接解出 \(X,Y\) 即可。询问次数为固定的 \(8\) 次。
ll ask(char op, ll k)
{
    cout << "? " << op << ' ' << k << endl;
    cout.flush();
    ll res; cin >> res;
    return res;
}
const ll M = 1e9;
ll x, y, A, B, C, D;
void solve(){
    int n; cin >> n;
    A = B = 2e9;
    for (int i=1; i<=n; ++i)
    {
        cin >> x >> y;
        A = min(A, x+y);
        B = min(B, y-x);
    }
    ask('L', M);
    ask('L', M);
    ask('D', M);
    C = ask('D', M);
    ask('R', M);
    ask('R', M);
    ask('R', M);
    D = ask('R', M);
    C = A - C + 4*M;
    D = B - D + 4*M;
    x = (C - D) / 2;
    y = (C + D) / 2;
    cout << "! " << x << ' ' << y << endl;
    cout.flush();
}
C. By the Assignment
题意
给一张无向带点权图,某些点点权未知,要使任意点对 \((x,y)\) 都满足以 \(x\) 为起点 \(y\) 为终点的所有简单路径的异或和相等,点权范围 \([0, V)\),求方案数。
题解
观察样例猜结论,归纳证明,可以得到:奇环上的所有点权必须为 0,偶环上的所有点权必须相等。
进而可知大小超过 2 的 bcc 中所有点权必须相等,且是否必须为 0 取决于能否二分图染色。
tarjan + 并查集,判掉原本就不合法的情况后容易维护出自由元的数量 \(s\),最后答案即为 \(V^s\)。
const int N = 2e5+5, M = 4e5+5;
int n, m, k, x[M], y[M], a[N];
vector <vector<pii>> e;
struct node_bcc
{
	int n, id, tp, bcc_n;
	vector<vector<pair<int, int>>> e;
	vector<vector<int>> bcc_node, bcc_edge;
	vector<int> dfn, low, st, ed, blk, ct;
	node_bcc(const vector<vector<pair<int, int>>> &e, int m) :
		n(e.size()), id(0), tp(0), bcc_n(0), e(e), dfn(n, -1), low(n, -1), st(m), ed(m), blk(m), ct(n)
	{
		for (int i = 0; i < n; i++) for (auto [v, w] : e[i])
		{
			assert(v >= 0 && v < n);
			assert(w >= 0 && w < m);
		}
		for (int i = 0; i < n; i++) if (dfn[i] == -1) dfs(i, 1);
		bcc_node.resize(bcc_n);
		for (int i = 0; i < n; i++) for (auto [v, w] : e[i]) bcc_node[blk[w]].push_back(i);
		vector<int> flg(n);
		for (auto &v : bcc_node)
		{
			vector<int> t;
			for (int x : v) if (!exchange(flg[x], 1)) t.push_back(x);
			swap(t, v);
			for (int x : v) flg[x] = 0;
		}
		for (int i = 0; i < n; i++) if (e[i].size() == 0)
		{
			bcc_node.push_back({i});
			bcc_edge.push_back({ });
			++bcc_n;
		}
	}
	void dfs(int u, bool rt)
	{
		dfn[u] = low[u] = id++;
		int cnt = 0;
		for (auto [v, w] : e[u]) if (!ed[w])
		{
			st[tp++] = w;
			ed[w] = 1;
			if (dfn[v] == -1)
			{
				dfs(v, 0);
				++cnt;
				cmin(low[u], low[v]);
				if (dfn[u] <= low[v])
				{
					ct[u] = cnt > rt;
					bcc_edge.push_back({ });
					do
					{
						bcc_edge[bcc_n].push_back(st[--tp]);
						blk[st[tp]] = bcc_n;
					} while (st[tp] != w);
					++bcc_n;
				}
			}
			else cmin(low[u], dfn[v]);
		}
	}
};
int col[N];
bool fl;
vector <int> g[N];
void dfs(int u, int f)
{
    for (int v : g[u]) if (v != f)
    {
        if (col[v] == col[u]) fl = 1;
        else if (!col[v]) col[v] = -col[u], dfs(v, u);
    }
}
int f[N];
int find(int x)
{
    return x == f[x] ? x : f[x] = find(f[x]);
}
bool merge(int x, int y)
{
    x = find(x), y = find(y);
    if (x == y) return 1;
    if (~a[x] && ~a[y] && a[x] != a[y]) return 0;
    if (~a[x]) a[y] = a[x];
    else if (~a[y]) a[x] = a[y];
    f[y] = x;
    return 1;
}
ll solve(){
    cin >> n >> m >> k; e.clear(); e.resize(n);
    for (int i=0; i<n; ++i) cin >> a[i], f[i] = i;
    for (int i=0; i<m; ++i)
    {
        cin >> x[i] >> y[i]; --x[i], --y[i];
        e[x[i]].push_back({y[i], i});
        e[y[i]].push_back({x[i], i});
    }
    node_bcc bcc(e, m);
    for (int i=0; i < bcc.bcc_n; ++i)
    {
        if (bcc.bcc_node[i].size() <= 2) continue;
        int st = bcc.bcc_node[i][0];
        for (int u : bcc.bcc_node[i])
        {
            if (!merge(u, st)) return 0;
        }
        for (int j : bcc.bcc_edge[i])
        {
            g[x[j]].push_back(y[j]);
            g[y[j]].push_back(x[j]);
        }
        fl = 0, col[st] = 1, dfs(st, 0);
        for (int u : bcc.bcc_node[i]) g[u].clear(), col[u] = 0;
        if (fl)
        {
            int& val = a[find(st)];
            if (val > 0) return 0;
            val = 0;
        }
    }
    int ans = 0;
    for (int i=0; i<n; ++i) if (a[i] == -1 && f[i] == i) ++ans;
    return qpow(k, ans);
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号