VP Codeforces Round 907 (Div. 2)


A. Sorting with Twos

题意:给你一个数组,你每次可以给前2i个数减一,问能不能使得数组非递减。

[2i,2i+11]这段数大小关系保持不变,看每段是不是升序关系就行了。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    for (int i = 1, j = 2; i < n; j *= 2) {
    	for (int k = i; k + 1 < j && k + 1 < n; ++ k) {
    		if (a[k] > a[k + 1]) {
    			std::cout << "NO\n";
    			return;
    		}
    	}

    	i = j;
    }

    std::cout << "YES\n";
}

B. Deja Vu

题意:n个数,q次操作,每次把所有2i的倍数都加上2i1。问最后每个数的值。

如果一个数是2i的倍数,那么加上2i1次方后最大就只能是2i1的倍数了。记每个数它的最大的2的整数幂的因子,每次操作把所有2x倍数都加到2x1里面去就行。每个数最多被操作30次。

点击查看代码
void solve() {
    int n, q;
    std::cin >> n >> q;
    std::vector<i64> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::vector<std::vector<int> > b(31);
    for (int i = 0; i < n; ++ i) {
    	for (int j = 30; j >= 0; -- j) {
    		if (a[i] % (1ll << j) == 0) {
    			b[j].push_back(i);
    			break;
    		}
    	}
    }

    while (q -- ) {
    	int x;
    	std::cin >> x;
    	for (int i = x; i <= 30; ++ i) {
    		for (auto & j : b[i]) {
    			a[j] += 1 << (x - 1);
    			b[x - 1].push_back(j);
    		}
    		b[i].clear();
    	}
    }

    for (int i = 0; i < n; ++ i) {
    	std::cout << a[i] << " \n"[i == n - 1];
    }
}

C. Smilo and Monsters

题意:n个数,你有一个x,每次你可以选择给一个数减一,然后x=x+1;或者让某个大于等于x的数减去x,然后x=0。问每个数变成0最少需要几次操作。

考虑模拟,从小到大一个一个减一,x留着打最大的,最后可能操作到剩下一个数,这时考虑分类讨论。
假设剩下m,如果m==1,答案加上1就好了。否则假设我们还执行y次减一操作,那么要满足x+y<=my, 得2y<=mx,这里需要向上取整。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::sort(a.begin(), a.end());
    int l = 0, r = n - 1;
    i64 ans = 0, x = 0;
    while (l < r) {
    	// std::cout << l << " " << r << "\n";
    	if (x + a[l] >= a[r]) {
    		ans += a[r] - x;
    		ans += 1;
    		a[l] = x + a[l] - a[r];
    		a[r] = 0;
    		x = 0;
    		-- r;
    		if (a[l] == 0) {
    			++ l;
    		}
    	} else {
    		x += a[l];
    		ans += a[l];
    		++ l;
    	}
    }

    if (l == r) {
    	// std::cout << ans << " " << a[r] << " " << x << "\n";
    	//x + y <= a[r] - y
    	//2y <= a[r] - x
    	if (a[r] == 1) {
    		ans += 1;
    	} else {
    		a[r] -= x;
    		ans += (a[r] + 1) / 2 + 1;
    	}
    }

    std::cout << ans << "\n";
}

D. Suspicious logarithms

题意:f(x)是最小的y,满足2y<=xg(x)是最小的z满足f(x)z<=x。求i=lrg(i)

[2i,2i+11]的数的f值都是i,则可以分段处理。对于每一段,xi,xi+11g值都是i,同样分段处理。

点击查看代码
void solve() {
	i64 l, r;
	std::cin >> l >> r;	
	Z ans = 0;
	while (l <= r) {
		i64 f = std::__lg(l);
		i64 x = (1ll << (f + 1)) - 1;
		// std::cerr << l << " " << x << "\n";
		i128 now = 1;
		for (i64 i = 0, last = 0; last <= std::min(x, r); now *= f, ++ i) {
			if (now <= l) {
				continue;
			}

			i64 L = std::max(l, last), R = std::min<i128>({x, r, now - 1});
			// std::cout << L << " " << R << " " << i << "\n";
			ans += (Z)(R - L + 1) * (i - 1);

			last = R + 1;
		}

		l = x + 1;
	}

	std::cout << ans << "\n";
}

F. A Growing Tree

题意:开始有一个节点,每次新增一个节点到节点v,保证形状是一棵树。或者给目前节点u的整棵子树都加上v。求最后每个节点的值。

用树状数组维护每个操作时间总共加的值,那么可以离线后跑dfs,每个点访问的时候把给它的每个值加到对应的操作时间上,然后这个点的答案就是它的添加时间到a的区间和。离开时把这个点增加的值删除即可。

点击查看代码
template <class T>
struct Fenwick {
    int n;
    std::vector<T> tr;

    Fenwick(int _n) {
        init(_n);
    }

    void init(int _n) {
        n = _n;
        tr.assign(_n + 1, {});
    }

    void add(int x, T v) {
        for (int i = x; i <= n; i += i & -i) {
            tr[i] += v;
        }
    }

    T query(int x) {
        T res = 0;
        for (int i = x; i; i -= i & -i) {
            res += tr[i];
        }
        return res;
    }

    T sum(int l, int r) {
        return query(r) - query(l - 1);
    }
};

void solve() {
    int q;
    std::cin >> q;
    std::vector<std::vector<int>> adj(q + 1);
    std::vector<std::vector<std::pair<int, int>>> g(q + 1);
    std::vector<int> id(q + 1);
    int n = 1;
    for (int i = 1; i <= q; ++ i) {
    	int op, x, y;
    	std::cin >> op >> x;
    	if (op == 1) {
    		-- x;
    		id[n] = i;
    		adj[x].push_back(n ++ );
    	} else {
    		-- x;
    		std::cin >> y;
    		g[x].push_back({i, y});
    	}
    }

    Fenwick<i64> tr(q + 1);
    std::vector<i64> ans(n);
    auto dfs = [&](auto self, int u) -> void {
    	for (auto & [t, v] : g[u]) {
    		tr.add(t, v);
    	}

    	ans[u] = tr.sum(id[u] + 1, q);
    	for (auto & v : adj[u]) {
    		self(self, v);
    	}

    	for (auto & [t, v] : g[u]) {
    		tr.add(t, -v);
    	}
    };

    dfs(dfs, 0);
    for (int i = 0; i < n; ++ i) {
    	std::cout << ans[i] << " \n"[i == n - 1];
    }
}
posted @   maburb  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示