​|–>传送门<–|​

A. King of String Comparison 双指针

给定字符串2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_02,计算满足2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_03字典序小于2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_042021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_05的个数。

直接双指针扫一下,扫到满足的前缀就直接进行计数。否则直接跳下一个。

#include <bits/stdc++.h>
#define int long long
using namespace std;

inline void solve(){
int n = 0; std::cin >> n;
std::string a, b; std::cin >> a >> b;
int ans = 0;
for(int l = 0, r = 0; r < n;){
if(l > r) r = l;
if(a[r] == b[r]) r++;
else if(a[r] < b[r]) ans += (n - r), l++;
else l = (r += 1);
}
std::cout << ans << std::endl;
}

signed main(){
solve();
return 0;
}

B. New Queries On Segment Deluxe 可持久化线段树

牛逼

2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_06棵可持久化线段树,将区间覆盖操作视为节点接入空树再区间加的操作。思路比较简单,实现有点难。

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 21420000;
const int INF = 0x3f3f3f3f;
int a[250005][4], row = 0;

//;

#define lson lc[rt], l,
#define rson rc[rt], mid + 1,
#define endl '\n'

int lc[N], rc[N], root[20005][16], val[N], lazy[N], tot;

int create(int rt){
int now = ++tot;
lc[now] = lc[rt], rc[now] = rc[rt];
val[now] = val[rt], lazy[now] = lazy[rt];
return now;
}

inline void push_up(int rt){ val[rt] = std::min(val[lc[rt]], val[rc[rt]]) + lazy[rt]; }

void build(int &rt, int l, int r, int bitt){
rt = ++tot;
if(l == r){
for(int i = 0; i < row; i++) if(bitt >> i & 1) val[rt] += a[l][i];
return;
}
int mid = l + r >> 1;
build(lson, bitt), build(rson, bitt);
push_up(rt);
}

int s = 0, t = 0, d = 0;

void update1(int &rt, int l, int r, int u){
rt = create(u); //cout << rt << endl;
if(s <= l && r <= t){
val[rt] += d, lazy[rt] += d;
return;
}
int mid = l + r >> 1;
if(s <= mid) update1(lson, lc[u]);
if(t > mid) update1(rson, rc[u]);
push_up(rt);
}

void update2(int &rt, int l, int r, int u, int v, int tmp = 0){
if(s <= l && r <= t){
rt = create(v); // cout << "DEBUG U21" << rt << endl;
val[rt] += d - tmp, lazy[rt] += d - tmp;
return;
}
tmp += lazy[u] - lazy[v];
rt = create(u); //cout << "DEBUG U22" << rt << endl;
int mid = l + r >> 1;
if(mid >= s) update2(lson, lc[u], lc[v], tmp);
if(mid < t) update2(rson, rc[u], rc[v], tmp);
push_up(rt);
}

int query(int rt, int l, int r){
if(l >= s && r <= t) return val[rt];
int mid = l + r >> 1, ans = INF; //cout << ans << endl;
if(mid >= s) ans = std::min(ans, query(lson));
if(mid < t) ans = std::min(ans, query(rson));
return ans + lazy[rt];
}

void solve(){
int n, m; cin >> row >> n >> m;
for (int k = 0; k < row; k++)
for (int i = 1; i <= n; i++) cin >> a[i][k];
//cout << "TAG" << endl;
for (int bitt = 0; bitt < (1 << row); bitt++) build(root[0][bitt], 1, n, bitt);
for (int i = 1; i <= m; i++){
int op, v; cin >> op >> v;
if (op == 1){
int k; cin >> k >> s >> t >> d, k--;
for (int bitt = 0; bitt < (1 << row); bitt++){
if (bitt >> k & 1) update1(root[i][bitt], 1, n, root[v][bitt]);
else root[i][bitt] = root[v][bitt];
}
}
else if (op == 2){
int k; cin >> k >> s >> t >> d, k--;
for (int bitt = 0; bitt < (1 << row); bitt++){
if (bitt >> k & 1) update2(root[i][bitt], 1, n, root[v][bitt], root[v][bitt ^ (1 << k)]);
else root[i][bitt] = root[v][bitt];
}
}
else if (op == 3){
cin >> s >> t;
cout << query(root[v][(1 << row) - 1], 1, n) << endl;
}
}
}


signed main(){
ios_base::sync_with_stdio(false);
//cout << N << endl;
solve();
return 0;
}

C. Werewolves 树形背包

待补

F. to Pay Respects 模拟

你正在进行一场2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_07轮的游戏,在游戏中,2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_08不会攻击你,但是会吟唱咒语。

在每轮游戏中,事件会按照以下顺序发生。

  1. 2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_09可以选择吟唱​​​Regeneration​​咒语
  2. 你可以选择吟唱​​Poison​​咒语
  3. 你可以用剑进行攻击,并造成2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_10点伤害
  4. 所有负面效果生效

2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_08有三个属性,血条2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_12、​​​Poison​​​效果叠加2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_13,​​​Regeneration​​​效果叠加2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_c++_14

每层​​Poison​​​效果可以产生2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_15伤害,如果有​​​Regeneration​​​效果就减去一层。每层​​Regeneration​​​效果可以产生2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_16回复。

现在你可以吟唱2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_17次法术,问对2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_08造成的最大伤害。

思路.1 2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_19做法

讲​​Poison​​​对​​Regeneration​​​产生的削弱效果视为攻击产生的效果,记录在每个点施加​​Poison​​​产生的攻击的效果。然后直接排序取前2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_17大攻击效果累加进答案即可。复杂度来自排序2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_19

#include <bits/stdc++.h>
#define int long long
using namespace std;

vector<int> atk;

inline void solve(){
int n, x, r, p, k; cin >> n >> x >> r >> p >> k;
string s; cin >> s; s = '@' + s;
int ans = x * n;
for(int i = 1; i <= n; i++){
if(s[i] == '1'){
atk.emplace_back((n - i + 1) * (p + r));
ans -= (n - i + 1) * r;
}
else{
atk.emplace_back((n - i + 1) * p);
}
}
sort(atk.begin(), atk.end(), [](const int &a, const int &b) { return a > b; });
for(int i = 0; i < k; i++) ans += atk[i];
cout << ans << endl;

}

signed main(){
solve();
return 0;
}

思路.2 2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_22做法

来自神犇队友。

首先将前2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_c++_23个怪兽回血的点设为放技能的点。如果不足2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_c++_23次技能就从头开始补技能。

那么可以用一个双指针,然后将后面的技能往前移动,同时更新贡献取最大值。

由于不需要排序,双指针扫2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_22

太妙了

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;

bitset<N> vis;

inline void solve(){
int n, x, r, p, k; cin >> n >> x >> r >> p >> k;
string s; cin >> s; s = '@' + s;
int res = n * x, cnt = 0, ans = -1;
for(int i = 1; i <= n; i++){
if(s[i] == '1'){
if(cnt < k){
vis[i] = true;
res += (n - i + 1) * p;
cnt++;
}
else res -= (n - i + 1) * r;
}
}
for(int i = 1; cnt < k; i++){
if(!vis[i]){
vis[i] = true;
res += (n - i + 1) * p;
cnt++;
}
}
ans = res;
for(int ll = 1, rr = n; ll < rr;){
if(vis[ll]) ll++;
else if(!vis[rr]) rr--;
else{
res += (n - ll + 1) * p - (n - rr + 1) * r - (n - rr + 1) * p;
ans = max(ans, res);
vis[rr] = 0, vis[ll] = 1;
}
}
cout << ans << endl;
}

signed main(){
solve();
return 0;
}

G. Max Pair Matching 思维

题目要求对给定2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_262021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_27进行两两顶点配对形成2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_07条边,边权的计算方式为2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_29。要求边权和最大。

首先考虑拆绝对值号,不妨令2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_30(读入时进行预处理),在权值和最大的前提下,显然会有2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_072021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_32产生负贡献,2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_072021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_34产生正贡献。那么如何确定每个数对提供正贡献还是负贡献?

由于2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_30一定成立,我们任取两对进行分析。要使得2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_36,显然需要2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_37。那么我们只需要根据2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_38的大小进行排序,然后取前2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_072021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_32作为负贡献,取后2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_072021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_34作为正贡献即可。

#include <bits/stdc++.h>
#define int long long
using namespace std;

struct node{
int a, b, sum;
node(int aa, int bb, int ss): a(aa), b(bb), sum(ss) {}
const bool operator< (const node &x) const { return sum < x.sum; }
};

std::vector<node> mp;

inline void solve(){
int n = 0; std::cin >> n;
for(int i = 1; i <= (n << 1); i++){
int a, b, sum; std::cin >> a >> b;
if(a > b) std::swap(a, b);
mp.emplace_back(node(a, b, a + b));
}
int ans = 0;
std::sort(mp.begin(), mp.end());
for(int i = 0; i <= n - 1; i++) ans -= mp[i].a;
for(int i = n; i < (n * 2); i++) ans += mp[i].b;
cout << ans << endl;
}

signed main(){
solve();
return 0;
}

J. ABC Legacy 小模拟

首先,2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include一定充当左括号,所以数量必不能超过2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_07。然后剩余的问题在于2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_02要充当的角色。

我们可以发现,要完成配对,需要2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_07个左括号和2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_07个右括号。那么考虑选一部分2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_02当左括号。显然对于左括号而言,根据贪心的思想越左越好,因此我们对于到补齐2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_07个左括号范围内的2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_02全部丢到队列里去,超出左括号的范围外的2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_02当作右括号与2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include匹配掉。

然后对于一定充当右括号的2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_53,我们按照队列的顺序逐个匹配即可。匹配的同时可以检查合法性。

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 1e5 + 10;

std::deque<int> q[3];
std::vector<std::pair<int, int>> ans;
//*-----------------------------------*//
#define fir first
#define sec second
#define mkp make_pair
//*----------------------------------*//
#define showYes cout <<"YES\n"
#define showNo cout <<"NO\n"
//*----------------------------------*//
inline void solve(){
int n = 0; std::cin >> n;
std::string s; cin >> s;
int cnta = 0, cntb = 0, cntc = 0;
for(auto x : s){
if(x == 'A') cnta++;
if(x == 'B') cntb++;
if(x == 'C') cntc++;
}
int cntbc = n - cnta;
if(cntbc < 0){ cout << "NO" << endl; return; }
for(int i = 0; i < 2 * n; i++){
if(s[i] == 'A') q[0].emplace_back(i);
else if(s[i] == 'B'){
if(cntbc){ q[1].emplace_back(i); cntbc--; }
else{
if(q[0].empty()) { showNo; return; }
ans.emplace_back(std::mkp(q[0].back(), i));
q[0].pop_back();
}
}
else if(s[i] == 'C'){
if(q[0].empty() && q[1].empty()) { showNo; return; }
if(q[1].size()){
ans.emplace_back(std::mkp(q[1].back(), i));
q[1].pop_back();
}
else if(q[0].size()){
ans.emplace_back(std::mkp(q[0].back(), i));
q[0].pop_back();
}
}
}
showYes;
for(auto x : ans) cout << x.fir + 1 << ' ' << x.sec + 1 << endl;
}

signed main(){
//int t = 0; cin >> t;
//while(t--)
solve();
return 0;
}

K. Amazing Tree

给定一颗2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_07个节点的树,可以从任意一个点开始2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_55,求最小字典序的后续遍历。

首先,对于字典序最小的要求,我们一定是从叶结点中的最小值开始遍历的。我们可以记录每个节点的度,然后倒序寻找度为2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_56的节点。

然后,我们对当前节点2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_57进行讨论,我们有两种策略:

  • 认为当前节点不是根节点:先将子树按最小权排序。如果发现当前子树中的最大最小值小于2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_58,那么显然此时输出2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_58不是最优策略,所以此时应当先2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_c++_602021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_61个子树(当作父节点向上走),再将2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_58加入答案。否则就先遍历前2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_c++_63个子树,然后将2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_58加入答案,再遍历最后一个子树;
  • 认为当前节点是根节点:先将子树按最小权排序,然后按照最小叶序依次2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_c++_60子树,最后将2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_58加入答案。

可以发现在2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_55时需要记录搜索的顺序,从而确定是否可以将子树作为父节点向上走。

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 2e5 + 10, INF = 1e9 + 7;
vector<int> g[N], ans;

#define pii pair<int, int>
#define mkp make_pair
#define fir first
#define sec second

int deg[N], w[N];

inline void solve(){
ans.clear();
int n = 0; std::cin >> n;
for(int i = 1; i <= n; i++) deg[i] = 0;
for(int i = 0; i <= n + 1; i++) g[i].clear();
for(int i = 1, u, v; i <= n - 1; i++){
cin >> u >> v;
g[u].emplace_back(v);
g[v].emplace_back(u);
deg[u]++, deg[v]++;
}
function<void(int, int)> getmin = [&](int u, int fa){
bool flag = true;
w[u] = INF;
for(auto nxt : g[u]){
if(nxt == fa) continue;
flag = false;
getmin(nxt, u);
w[u] = min(w[u], w[nxt]);
}
if(flag) w[u] = u;
};
function<void(int, int, int)> dfs = [&](int u, int fa, int dir){
vector<pii> sot;
for(auto v : g[u]){
if(v == fa) continue;
sot.emplace_back(mkp(w[v], v));
}
if(!sot.size()) { ans.emplace_back(u); return; }
sort(sot.begin(), sot.end());
if(dir == 0){
for(auto x : sot) dfs(x.sec, u, 0);
ans.emplace_back(u);
} else {
for(int i = 0; i < sot.size() - 1; i++) dfs(sot[i].sec, u, 0);
if(u > sot.back().fir) dfs(sot.back().sec, u, 0), ans.emplace_back(u);
else ans.emplace_back(u), dfs(sot.back().sec, u, 1);
}
};
int st = 0;
for(int i = n; i >= 1; --i) if(deg[i] == 1) st = i;
getmin(st, 0);
dfs(st, 0, 1);
for(auto x : ans) cout << x << ' ';
cout << "\n";
}

signed main(){
ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t = 0; std::cin >> t;
while(t--) solve();
return 0;
}

L. Jason ABC

给定长度为2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_682021 ICPC Southeastern Europe Regional Contest ABFGJKLN_c++_69构成的字符串,每次操作可以选择一段连续的区间将其全部修改为2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_70中的一个字符。要求你在最小操作次数下将给定的字符串修改为包含2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_072021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_072021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_02以及2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_072021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_53的字符串。求最小修改次数以及修改操作。

首先可以确定,最大修改次数不会超过2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_77次:

首先我们预处理三个前缀2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#define_78分别表示到位置2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_79为止三个字母的前缀和。

  • 2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_80次:已经符合要求,不需要再修改
  • 2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_81次:只需要修改一个区间2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_82即可。如果假设将区间2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_82变为2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_84,那么要求2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_852021 ICPC Southeastern Europe Regional Contest ABFGJKLN_c++_86。那么直接双指针找即可。
  • 2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_87次:找到最小的2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_88,使得2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_89中出现次数最多的字符恰出现了2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_90次。那么把后面直接修改两次改为剩余两个字符的两段即可。
#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;
int cnt[N][4];


inline void solve(){
int n = 0; cin >> n;
string s; cin >> s; s = '@' + s;
auto change1 = [&](char c){
int x = (c - 'A' + 1) % 3 + 1, y = (c - 'A' + 2) % 3 + 1;
for(int l = 1, r = 1; l <= 3 * n; ){
if(l > r) r = l;
while((cnt[r][x] - cnt[l - 1][x] < cnt[3 * n][x] - n || cnt[r][y] - cnt[l - 1][y] < cnt[3 * n][y] - n) && r <= 3 * n) r++;
if(cnt[r][x] - cnt[l - 1][x] == cnt[3 * n][x] - n && cnt[r][y] - cnt[l - 1][y] == cnt[3 * n][y] - n){
return cout << 1 << endl << l << ' ' << r << ' ' << c << endl, true;
}
else l++;
}
return false;
};
auto change2 = [&](char c, int maxc){
int x = (c - 'A' + 1) % 3, y = (c - 'A' + 2) % 3;
char X = x + 'A', Y = y + 'A';
cout << 2 << endl;
cout << maxc + 1 << ' ' << maxc + n - cnt[maxc][x + 1] << ' ' << X << endl;
cout << maxc + n - cnt[maxc][x + 1] + 1 << ' ' << 3 * n << ' ' << Y << endl;

};
for(int i = 1; i <= 3 * n; i++){
for(int j = 1; j <= 3; j++) cnt[i][j] = cnt[i - 1][j];
if(s[i] == 'A') cnt[i][1]++;
if(s[i] == 'B') cnt[i][2]++;
if(s[i] == 'C') cnt[i][3]++;
}
if(cnt[3 * n][1] == cnt[3 * n][2] && cnt[3 * n][2] == n){ std::cout << "0\n"; return; }
if(change1('A') || change1('B') || change1('C')) return;
int maxc = 0;
char maxch;
for(int i = 1; i <= 3 * n; i++) if(!maxc && cnt[i][s[i]-'A' + 1] == n) maxc = i, maxch = s[i];
change2(maxch, maxc);
}

signed main(){
solve();
return 0;
}

N. A-series 思维

2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_算法_91种,每种纸2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_#include_79的大小是第2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_93张纸大小的两倍。

现在给你每种纸的数量,每次你可以选择一张纸对其进行对折,然后剪成两半。问能否通过剪操作变为目标纸张数量。

如果正着剪,显然会爆2021 ICPC Southeastern Europe Regional Contest ABFGJKLN_i++_94。那么不妨考虑倒序合并目标纸张。看够不够。

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 2e5 + 10;
int a[N], b[N];

inline void solve(){
int n = 0, ans = 0; std::cin >> n;
for(int i = 1; i <= n + 1; i++) cin >> a[i];
for(int i = 1; i <= n + 1; i++) cin >> b[i];
for(int i = n + 1; i > 1; --i){
int left = b[i] - a[i];
if(left < 0) continue;
(left += 1) >>= 1,b[i] -= left * 2, b[i - 1] += left; //向上取整合并纸张
ans += left; //计数
}
for(int i = 1; i <= n; i++){
if(b[i] > a[i]){ cout << -1 << endl; return; } //检查够不够
}
cout << ans << endl;
}

signed main(){
solve();
return 0;
}