QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#585452#5415. RopewayPonyHexRE 0ms0kbC++203.8kb2024-09-23 20:52:292024-09-23 20:52:41

Judging History

你现在查看的是最新测评结果

  • [2024-09-23 20:52:41]
  • 评测
  • 测评结果:RE
  • 用时:0ms
  • 内存:0kb
  • [2024-09-23 20:52:29]
  • 提交

answer

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
#define ll long long
#define double long double
#define lc u<<1
#define rc u<<1|1
#define X first
#define Y second
//#define int long long
const int N = 5e5 + 50;
const int M = 5e5 + 5;
const ll maxm = 1e18 + 5;
const ll mod = 998244353;
int dx[] = { -1,0,1,0 };
int dy[] = { 0,1,0,-1 };
//random_shuffle(id + 1, id + n + 1);
ll ksm(ll a, ll b);
ll gcd(ll a, ll b);

ll n, k, q;
ll a[N];
ll b[N];
string str;
ll dp[N] = { 0 };//表示在以第i个位置结尾的最小代价
ll base[N];

//unordered_map<ll, ll>has;//

vector<ll>po;

void solve()
{
	//感觉就是个dp,但是这n,q有点太大了点,
	//对于每个q都用n的复杂度跑,感觉会t
	//但是之前,我们已经获取了一部分,(在更改的元素之前的序列)
	//那部分,我们是可以接着用的,每次我们从那个地方开始,能优化一下
	//试试
	//怎么还有位置是要必须建,等等还有这种好事
	//为1的位置相当于把整个数列进行了划分
	//到单点修改导致的决策影响仅能影响到下一个一的位置
	//在往后的决策都直接加上前置的决策即可

	cin >> n >> k;
	for (int i = 1; i <= n; i++) {
		//cin >> a[i];
		scanf("%d", &a[i]);
	}
	cin >> str; str = "1" + str;
	str = str + "1"; a[0] = 0; a[n + 1] = 0;
	for (int i = 1; i <= n + 1; i++) {
		//if (str[i] != '1')dp[i] = maxm;
		//else dp[i] = 0;
		base[i] = maxm;
	}
	base[0] = 0;
	//在头尾都放置1
	//我想想,思路其实可以优化一下,每次其实只要从一个1到达一个1即可
	//在dp的时候我们暂且认为 1 的位置值为0 
	//这样dp中存的就是区间决策,最后加上所有1的位置的dp和a
	//感觉像什么,分块dp?

	for (int i = 0; i <= n + 1; i++) {
		if (str[i] == '1')
			b[i] = 0;
		else b[i] = a[i];
	}

	for (int i = 0; i <= n + 1; i++) {
		if (str[i] == '1')po.push_back(i);
	}

	for (auto p = po.begin() + 1; p != po.end(); p++) {
		ll st = *(p - 1), ed = *p;
		//走出从st+1到ed;
		for (int i = st + 1; i <= ed; i++) {//当前位置
			//对于每个位置,都能从前置的一定节点到达
			for (int j = i - 1; j >= st && i - j <= k; j--) {//前置位置
				if (j == st) base[i] = min(base[i], 0 + b[i]);
				else
					base[i] = min(base[i], base[j] + b[i]);
			}
		}
	}

	ll ans = 0;
	for (auto p = po.begin(); p != po.end(); p++) {
		ans += base[*p]; ans += a[*p];
	}
	//cout << ans << endl;

	cin >> q;
	for (int i = 1; i <= q; i++) {
		ll pos, val; //cin >> pos >> val;
		scanf("%d%d", &pos, &val);
		if (str[pos] == '1') {
			ll dis = val - a[pos];
			ans += dis;
			cout << ans << endl;
			ans -= dis;
			continue;
		}
		//a[pos] += val;
		ll dis = 0;
		if (str[pos] != '1') {
			ll pb = b[pos];
			b[pos] = val;
			ll ed = lower_bound(po.begin(), po.end(), pos) - po.begin();
			ll st = ed - 1;
			ed = po[ed];
			st = po[st];
			ll pr = base[ed];
			for (int ii = st + 1; ii <= ed; ii++) {
				dp[ii] = maxm;
			}
			for (int ii = st + 1; ii <= ed; ii++) {
				for (int j = ii - 1; j >= st && ii - j <= k; j--) {//前置位置
					if (j == st) dp[ii] = min(dp[ii], 0 + b[ii]);
					else
						dp[ii] = min(dp[ii], dp[j] + b[ii]);
				}
			}
			b[pos] = pb;
			ll now = dp[ed];
			ans += (now - pr);
			dis = (now - pr);
			cout << ans << endl;
			ans -= dis;
		}
	}
	po.clear();
	return;
}


signed main()
{
	/*
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);*/
	int T = 1;
	cin >> T;
	while (T--)
		solve();
	return 0;
}

/*PonyHex*/


ll ksm(ll a, ll b) {
	ll base = a;
	ll ans = 1;
	while (b) {
		if (b & 1)ans *= base % mod;
		ans %= mod;
		base *= base; base %= mod;
		b >>= 1;
	}
	return ans % mod;
}
ll gcd(ll a, ll b) {
	return b ? gcd(b, a % b) : a;
}

详细

Test #1:

score: 0
Runtime Error

input:

3
10 3
5 10 7 100 4 3 12 5 100 1
0001000010
2
2 3
6 15
5 6
1 1 1 1 1
00000
1
3 100
5 6
1 1 1 1 1
00100
1
3 100

output:


result: