CF601E A Museum Robbery 解题报告
最初给定
n 个物品以及背包容量k ,有q 次操作,操作有三种:
1 v w
在背包里添加一个体积为v 价值为w 的物品2 x
删除编号为x 的物品3
查询背包总和,以\sum\limits_{m=1}^{k}{s(m)*p^{m-1}\ \bmod\ q} 的形式输出
n \leq 5000,k \leq 1000,q \leq 30000 ,保证操作1 的个数不超过10000 ,且至少有一个操作3 。
解题思路:
首先我们考虑,在背包里加入一个物品是
接下来观察题目的前两个操作,发现如果我们把最开始的物品看作在时间点
确定了算法之后,就开始考虑怎么写。首先我们记操作 vector
来保存这个节点代表的区间存在的物品。我们发现这里实际上不好合并,所以我们采用标记永久化的方法。
在分治过程中,我们每访问到一个节点考虑一个额外的
void solve(int p,ll *f) {
ll g[N];
for (int i = 0;i <= sto;++i) g[i] = f[i];
for (auto now : tree[p].vec) {
Add(g,now);//将物品 now 添加到 g 中。
}
if (tree[p].l == tree[p].r) {
Output();
return ;
} else {
//注意此处下传是 g 数组,已经添加过物品了。
solve(p << 1,g);
solve(p << 1 | 1,g);
}
}
时间复杂度 memset
。
代码:
const int N = 1e5 + 10;
const ll base = 1e7 + 19;
const ll mod = 1e9 + 7;
struct item {
int x,y,v,w;
}E[N];
struct node {
int l,r;
vector <item> vec;
}tree[N<<2];
ll qwq[N];
int tot,n,q,sto;
void build(int p,int l,int r) {
tree[p].l = l,tree[p].r = r;
if (l == r) {
return ;
}
int mid = (l + r) >> 1;
build(p << 1,l,mid);
build(p << 1 | 1,mid + 1,r);
}
void change(int p,int x,int y,int num) {
if (tree[p].l >= x && tree[p].r <= y) {
tree[p].vec.push_back(E[num]);
return ;
}
int mid = (tree[p].l + tree[p].r) >> 1;
if (x <= mid) change(p << 1,x,y,num);
if (y > mid) change(p << 1 | 1,x,y,num);
}
void solve(int p,ll *f) {
ll g[N];
for (int i = 0;i <= sto;++i) g[i] = f[i];
for (auto now : tree[p].vec) {
for (int j = sto;j >= now.v;--j) {
g[j] = max(g[j],g[j - now.v] + now.w);
}
}
if (tree[p].l == tree[p].r) {
ll ans = 0;
for (int i = sto;i >= 1;--i) ans = (ans * base + g[i]) % mod;
printf("%lld\n",ans);
} else {
solve(p << 1,g);
solve(p << 1 | 1,g);
}
}
signed main() {
read(n,sto);
for (int i = 1;i <= n;++i) {
int v,w;read(w,v);
E[++tot] = {1,-1,v,w};
}
int tt = 1;
read(q);
for (int i = 1;i <= q;++i) {
int opt;read(opt);
if (opt == 1) {
int v,w;read(w,v);
E[++tot] = {tt,-1,v,w};
}
if (opt == 2) {
int x;read(x);
E[x].y = tt - 1;
}
if (opt == 3) {
++tt;
}
}
--tt;
build(1,1,tt);
for (int i = 1;i <= tot;++i) {
if (E[i].y == -1) E[i].y = tt;
if (E[i].x <= E[i].y) {
change(1,E[i].x,E[i].y,i);
}
}
solve(1,qwq);
return 0;
}
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭