社区讨论

截止8.1悬赏5元求卡常,不WA只TLE

P8349 [SDOI/SXOI2022] 整数序列参与者 4已保存回复 14

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
14 条
当前快照
1 份
快照标识符
@mdi2xj0s
此快照首次捕获于
2025/07/25 08:24
8 个月前
此快照最后确认于
2025/11/04 06:29
4 个月前
查看原帖
代码算小清新的。
各位大佬帮我这个蒟蒻看看,这份代码目前只能获得和暴力同样的分数。
我非常怀疑,到底是我代码复杂度有问题还是单纯卡常?
应该没有 WA 的问题,本地拍了 10310^3 组大数据无误,但是速度比较慢,一组大概 12s12 s 的样子。
代码中 mark\text{mark} 用来记录小颜色配大颜色的时候,跳过没有用的大颜色的位置,这些断点的位置。剩余应该简单。
CPP
#include <bits/stdc++.h>
using namespace std;
#define int long long

const int N = 300010, INF = 1e18;

int n, a[N], m, B;
int s[N], val[N], sv[N];
vector<int> cnt[N];
set<int> ps[N];
int g[1000][1000];
int buck[N * 2], mark[N], tong[N];

inline int bf(int x, int y)
{
	vector<int> v;
	int px = 0, py = 0;
	while (px <= (int)cnt[x].size() - 1 || py <= (int)cnt[y].size() - 1)
		if (px == (int)cnt[x].size()) v.push_back(cnt[y][py ++ ]);
		else if (py == (int)cnt[y].size()) v.push_back(cnt[x][px ++ ]);
		else if (cnt[x][px] < cnt[y][py]) v.push_back(cnt[x][px ++ ]);
		else v.push_back(cnt[y][py ++ ]);
	int last = 0, res = -1e18;
	vector<int> us;
	buck[0 + N] = 0;
	for (int i = v[0] - 1, cur = 0; i >= 0; i -- )
		cur += a[i], buck[0 + N] = min(buck[0 + N], cur);
	int tmp = buck[0 + N];
	for (auto i : v)
	{
		s[i] = s[last] + (a[i] == x ? 1 : -1);
		sv[i] = sv[last] + val[i];
		last = i;
		if (buck[s[i] + N] != -1) res = max(res, sv[i] - sv[buck[s[i] + N]]);
		if (buck[s[i] + N] == -1) us.emplace_back(s[i] + N), buck[s[i] + N] = i;
		else if (sv[buck[s[i] + N]] > sv[i]) buck[s[i] + N] = i;
		
		if (mark[i]) 
		{
			for (auto i : us) buck[i] = -1;
			us.clear();
			buck[0 + N] = tmp;
			last = 0;
		}
	}
	for (auto i : us) buck[i] = -1;
	return res;
}

signed main()
{
	memset(buck, -1, sizeof buck);
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i ++ )
	{
		cin >> a[i];
		cnt[a[i]].emplace_back(i);
	}
	B = sqrt(n);
	vector<int> v;
	for (int i = 1; i <= n; i ++ )
		if ((int)cnt[i].size() > B) v.push_back(i), tong[i] = v.size();
	for (auto i : v)
		for (auto j : cnt[i])
			ps[i].insert(j);
	for (int i = 1; i <= n; i ++ ) cin >> val[i];
	for (int i = 0; i < v.size(); i ++ )
		for (int j = i + 1; j < v.size(); j ++ )	
			g[tong[v[j]]][tong[v[i]]] = g[tong[v[i]]][tong[v[j]]] = bf(v[i], v[j]); //return 0;
	while (m -- )
	{
		int x, y;
		cin >> x >> y;
		if ((int)cnt[x].size() <= B && (int)cnt[y].size() <= B) cout << bf(x, y) << "\n";
		else if ((int)cnt[x].size() > B && (int)cnt[y].size() > B) cout << g[tong[x]][tong[y]] << "\n";
		else
		{
			if (cnt[x].size() > cnt[y].size()) swap(x, y);
			vector<int> er, us;
			for (auto i : cnt[x])
			{
			    ps[y].insert(i);
				auto it = ps[y].find(i);
				if (it != ps[y].begin())
				{
					auto it2 = it;
					it2 -- ;
					er.push_back(*it2);
					ps[y].erase(*it2);
				}
				auto it2 = it; it2 ++ ;
				if (it2 != ps[y].end())
				{
					er.push_back(*it2);
					ps[y].erase(*it2);
				}
				ps[y].erase(i);
			}
			for (auto i : er) ps[y].insert(i);
			sort(er.begin(), er.end());
			for (int i = 0; i < (int)er.size() - 1; i ++ )
			{
				auto id = ps[y].find(er[i]);
				id ++ ;
				if (er[i + 1] != (*id)) mark[er[i]] = 1, us.push_back(er[i]);
			}
			swap(er, cnt[y]);
			cout << bf(x, y) << "\n";
			swap(er, cnt[y]);
			for (auto i : us) mark[i] = 0;
		}
	}
	return 0;
}

回复

14 条回复,欢迎继续交流。

正在加载回复...