KDOI-3还原数据题解
「KDOI-03」还原数据
题目描述
小 E 正在做一道经典题:
给定一个长度为
:对于所有 , 。 :对于所有 , 。
题目要求输出所有操作结束后的最终序列
小 E 迅速写了一份代码提交,但是发现,由于宇宙射线的影响,输入数据出现了一些小问题。具体地,对于所有
当然,可能会有多种合法的输入数据,你需要找到其中任意一种。数据保证有解。
输入格式
从标准输入读入数据。
本题有多组测试数据。
第一行一个正整数
对于每组测试数据,第一行两个非负整数
第二行
接下来
接下来一行
输出格式
输出到标准输出。
本题开启自定义校验器(Special Judge)。
对于每组测试数据,设共有
你需要保证
样例 #1
样例输入 #1
1
5 3
1 2 3 4 5
2 3 5
1 3 4 2
2 1 1
20 2 5 6 5
样例输出 #1
3 20
提示
【样例 1 解释】
所有合法输出需要满足:第
【样例 2】
见选手文件中的 restore/restore2.in
与 restore/restore2.ans
。
【样例 3】
见选手文件中的 restore/restore3.in
与 restore/restore3.ans
。
【数据范围】
记
对于
对于
对于另外
对于另外
对于
【校验器】
本题样例文件较大,无法在附件中下载,请在选手文件中查看。
为了方便测试,在
编译命令为:
g++ checker.cpp -o checker -std=c++14
使用方式为:
./checker <inputfile> <outputfile> <answerfile>
校验器可能会返回以下状态中的其中一种:
:表示你的输出完全正确。 :表示你的输出在第 个测试数据出错。
【提示】
本题输入输出量较大,推荐使用较快的输入输出方式。
KDOI 出题组温馨提示:多测不清空,爆零两行泪。
题解
首先因为
引理:对于一次max操作,这个值
证明,反证法,如果不是这样,那么取一个更大的数字,区间的最小值在经过了后面的操作之后会大于最终值
那么因为数据保证有解,我们就可以取等号,那么问题显而易见,我们开一棵维护区间最小值和区间加的线段树,倒序对于区间加改为减,每次max操作输出区间最小值即可
//fc D:\编程\C++\restore3.ans D:\编程\C++\restore3.out
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 505500
//#define int long long
#define ll long long
struct node {
int l, r;ll mn, add;
}t[N << 2];
struct ask {
int id, l, r;ll x;
}a[N];
#define lc x<<1
#define rc x<<1|1
int s[N], n, m, q, tot;
ll ans[N];
void build(int l,int r,int x) {
int mid = l + r >> 1;
t[x] = { l,r,0x3f3f3f3f3f3f3f3f,0 };
if (l == r) {
scanf("%lld", &t[x].mn);
return;
}
build(l, mid, lc);
build(mid + 1, r, rc);
t[x].mn = min(t[lc].mn, t[rc].mn);
}
inline void pushup(int x) {
t[x].mn = min(t[lc].mn, t[rc].mn);
}
inline void pushdown(node& a, node& b, node& c) {
b.add += a.add, c.add += a.add;
b.mn += a.add, c.mn += a.add;
a.add = 0;
}
inline void pushdown(int x) {
pushdown(t[x], t[lc], t[rc]);
}
void change(int l, int r, int x, ll k) {
if (l <= t[x].l && t[x].r <= r) {
t[x].add += k;
t[x].mn += k;
return;
}
pushdown(x);
int mid = t[x].l + t[x].r >> 1;
if (l <= mid)change(l, r, lc, k);
if (mid < r)change(l, r, rc, k);
pushup(x);
}
ll find(int l, int r, int x) {
if (l <= t[x].l && t[x].r <= r) {
return t[x].mn;
}
pushdown(x);
ll ans = 0x3f3f3f3f3f3f3f3f;
int mid = t[x].l + t[x].r >> 1;
if (l <= mid)ans = min(ans, find(l, r, lc));
if (mid < r)ans = min(ans, find(l, r, rc));
pushup(x);
return ans;
}
void init() {
tot = 0;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)scanf("%d", &s[i]);
for (int i = 1; i <= m; i++) {
int op, l, r;ll k;
scanf("%d%d%d", &op, &l, &r);
if (op == 1) {
scanf("%lld", &k);
a[i] = { op,l,r,k };
continue;
}
a[i] = { op,l,r,-1ll };
}
build(1, n, 1);
for (int i = m; i > 0; i--) {
if (a[i].id == 1) {
change(a[i].l, a[i].r, 1, -a[i].x);
continue;
}
ans[++tot] = find(a[i].l, a[i].r, 1);
}
for (int i = tot; i; i--) {
printf("%lld ", ans[i]);
}
puts("");
}
signed main() {
// freopen("restore2.in","r",stdin);
// freopen("restore2.out","w",stdout);
int t;
scanf("%d", &t);
while (t--) {
init();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!