QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#585452 | #5415. Ropeway | PonyHex | RE | 0ms | 0kb | C++20 | 3.8kb | 2024-09-23 20:52:29 | 2024-09-23 20:52:41 |
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;
}
Details
Tip: Click on the bar to expand more detailed information
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