Codechef MGCHGYM Misha and Gym 容斥、背包、Splay
简化题意:给定一个长度为\(N\)的数列,\(Q\)个操作:
\(1\,x\,a\)、将数列中第\(x\)个元素改为\(a\)
\(2\,l\,r\)、反转子序列\([l,r]\)
\(3\,l\,r\,w\)、询问区间\([l,r]\)中是否存在若干个数和为\(w\),一个数只能取一次
注意:在整个过程中,在数列中出现过的数的种数不会超过\(K(K \leq 10)\)。
注意到最后一个条件很奇怪……
考虑询问实际上是:最开始给出不超过\(10\)个数\(a_1,...,a_{10}\),每一次给出\(a_1,...,a_{10}\)分别最多能够取的次数,问是否能够取出若干使得和为\(w\);而前两个操作只是在改变这个能够取的最多次数。
不妨更进一步想,试着求能够取的方案数……
是不是想到了……
那么我们可以直接按照硬币购物的方法去做
先用\(a_1\)到\(a_{10}\)跑完全背包,对于每一次询问进行容斥,强制令某一些数字超出使用次数并计算答案。那么每一次询问的复杂度是\(2^{10}\)的。
最后使用\(Splay\)维护一下前两个修改操作,题目就做完了。
关于完全背包存不下那么多方案数的问题……直接模\(10^9+7\)
#include<bits/stdc++.h>
#define lch Tree[x].ch[0]
#define rch Tree[x].ch[1]
#define root Tree[0].ch[0]
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c) && c != EOF){
if(c == '-')
f = 1;
c = getchar();
}
if(c == EOF)
exit(0);
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return f ? -a : a;
}
const int MAXN = 1e5 + 10 , MOD = 1e9 + 7;
int dp[MAXN] , dir[11] , *cnt , N , Q , cntN , cntL;
map < int , int > lsh;
struct node{
int ch[2] , sz , fa , val , sum[11];
bool mark;
}Tree[MAXN];
struct query{
int ind , a , b , c;
}que[MAXN];
inline int getL(int x){
if(!lsh.count(x)){
lsh[x] = ++cntL;
dir[cntL] = x;
}
return lsh[x];
}
inline bool son(int x){
return Tree[Tree[x].fa].ch[1] == x;
}
inline void pushup(int x){
for(int i = 1 ; i <= 10 ; ++i)
Tree[x].sum[i] = Tree[lch].sum[i] + Tree[rch].sum[i] + (Tree[x].val == i);
Tree[x].sz = Tree[lch].sz + Tree[rch].sz + 1;
}
inline void rotate(int x){
bool f = son(x);
int y = Tree[x].fa , z = Tree[y].fa , w = Tree[x].ch[f ^ 1];
Tree[x].fa = z;
Tree[z].ch[son(y)] = x;
Tree[x].ch[f ^ 1] = y;
Tree[y].fa = x;
Tree[y].ch[f] = w;
if(w)
Tree[w].fa = y;
pushup(y);
}
inline void Splay(int x , int tar){
while(Tree[x].fa != tar){
if(Tree[Tree[x].fa].fa != tar)
rotate(son(x) == son(Tree[x].fa) ? Tree[x].fa : x);
rotate(x);
}
pushup(x);
}
inline void mark(int x){
if(!x)
return;
swap(lch , rch);
Tree[x].mark ^= 1;
}
inline void pushdown(int x){
if(Tree[x].mark){
mark(lch);
mark(rch);
Tree[x].mark = 0;
}
}
void insert(int &x , int rk , int val , int fa){
if(!x){
x = ++cntN;
Tree[x].fa = fa;
Tree[x].sz = 1;
Tree[x].val = val;
Splay(x , 0);
return;
}
if(Tree[lch].sz >= rk)
insert(lch , rk , val , x);
else
insert(rch , rk - 1 - Tree[lch].sz , val , x);
}
void findKth(int x , int rk , int tar){
pushdown(x);
if(Tree[lch].sz == rk)
Splay(x , tar);
else
if(Tree[lch].sz > rk)
findKth(lch , rk , tar);
else
findKth(rch , rk - Tree[lch].sz - 1 , tar);
}
inline void modify(int x , int val){
findKth(root , x , 0);
--Tree[root].sum[Tree[root].val];
++Tree[root].sum[Tree[root].val = val];
}
inline void rev(int l , int r){
findKth(root , l - 1 , 0);
findKth(root , r + 1 , root);
mark(Tree[Tree[root].ch[1]].ch[0]);
}
inline void query(int l , int r){
findKth(root , l - 1 , 0);
findKth(root , r + 1 , root);
cnt = Tree[Tree[Tree[root].ch[1]].ch[0]].sum;
}
void init(){
dp[0] = 1;
for(int i = 1 ; i <= cntL ; ++i)
for(int j = dir[i] ; j <= 1e5 ; ++j)
dp[j] = (dp[j] + dp[j - dir[i]]) % MOD;
}
int dfs(int x , int sum , int flg){
if(sum < 0)
return 0;
if(x > cntL)
return flg * dp[sum];
return (dfs(x + 1 , sum , flg) + dfs(x + 1 , sum - (cnt[x] + 1) * dir[x] , flg * -1) + 1ll * MOD) % MOD;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
N = read();
Q = read();
insert(root , 0 , 0 , 0);
for(int i = 1 ; i <= N ; ++i)
insert(root , i , getL(read()) , 0);
insert(root , N + 1 , 0 , 0);
for(int i = 1 ; i <= Q ; ++i){
que[i].ind = read();
que[i].a = read();
que[i].b = read();
if(que[i].ind == 3)
que[i].c = read();
if(que[i].ind == 1)
que[i].b = getL(que[i].b);
}
init();
for(int i = 1 ; i <= Q ; ++i)
switch(que[i].ind){
case 1:
modify(que[i].a , que[i].b);
break;
case 2:
rev(que[i].a , que[i].b);
break;
case 3:
query(que[i].a , que[i].b);
puts(dfs(1 , que[i].c , 1) ? "Yes" : "No");
}
return 0;
}
Codechef MGCHGYM Misha and Gym 容斥、背包、Splay的更多相关文章
- BZOJ 1042: [HAOI2008]硬币购物 容斥+背包
1042: [HAOI2008]硬币购物 Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请 ...
- Atcoder Grand Contest 038 E - Gachapon(Min-Max 容斥+背包)
Atcoder 题面传送门 & 洛谷题面传送门 我竟然能独立做出 Ag 的 AGC E,incredible!更新了 Atcoder 做题难度上限( 首先按照套路 Min-Max 容斥,\(a ...
- 洛谷 P4707 - 重返现世(扩展 Min-Max 容斥+背包)
题面传送门 首先看到这种求形如 \(E(\max(T))\) 的期望题,可以套路地想到 Min-Max 容斥 \(\max(S)=\sum\limits_{T\subseteq S}(-1)^{|T| ...
- 牛客练习赛64 D【容斥+背包】
牛客练习赛64 D.宝石装箱 Description \(n\)颗宝石装进\(n\)个箱子使得每个箱子中都有一颗宝石.第\(i\)颗宝石不能装入第\(a_i\)个箱子.求合法的装箱方案对\(99824 ...
- P1450 [HAOI2008]硬币购物(完全背包+容斥)
P1450 [HAOI2008]硬币购物 暴力做法:每次询问跑一遍多重背包. 考虑正解 其实每次跑多重背包都有一部分是被重复算的,浪费了大量时间 考虑先做一遍完全背包 算出$f[i]$表示买价值$i$ ...
- ARC 101E.Ribbons on Tree(容斥 DP 树形背包)
题目链接 \(Description\) 给定一棵\(n\)个点的树.将这\(n\)个点两两配对,并对每一对点的最短路径染色.求有多少种配对方案使得所有边都至少被染色一次. \(n\leq5000\) ...
- BZOJ-1042:硬币购物(背包+容斥)
题意:硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. 思路:这么老的题,居然今天才做到. ...
- Luogu-P1450 [HAOI2008]硬币购物-完全背包+容斥定理
Luogu-P1450 [HAOI2008]硬币购物-完全背包+容斥定理 [Problem Description] 略 [Solution] 上述题目等价于:有\(4\)种物品,每种物品有\(d_i ...
- BZOJ 1042 [HAOI2008]硬币购物(完全背包+容斥)
题意: 4种硬币买价值为V的商品,每种硬币有numi个,问有多少种买法 1000次询问,numi<1e5 思路: 完全背包计算出没有numi限制下的买法, 然后答案为dp[V]-(s1+s2+s ...
随机推荐
- React 入门学习笔记整理(六)—— 组件通信
1.父子组件通信 1)父组件与子组件通信,使用Props 父组件将name传递给子组件 <GreateH name="kitty"/> 子组件通过props接收父组件的 ...
- KVM虚拟化研究-1
使用qemu-img创建镜像 例子: [root@HOST31 rybtest]# qemu-img create -f raw /rybtest/test1.raw 1G 使用qemu-img查看镜 ...
- Kotlin入门(19)Android的基础布局
线性布局线性布局LinearLayout是最常用的布局,顾名思义,它下面的子视图像是用一根线串了起来,所以其内部视图的排列是有顺序的,要么从上到下垂直排列,要么从左到右水平排列.排列顺序只能指定一维方 ...
- WRT 下 C++ wstring, string, String^ 互转
由于项目原因,需要引入C++. wstring 与 string 的互转研究了一段时间,坑主要在于使用下面这种方式进行转换,中文会乱码 wstring ws = L"这是一段测试文字&quo ...
- maven——依赖管理
管理包依赖是 Maven 核心功能之一,下面通过如何引入 jar 包:如何解析 jar 包依赖:包冲突是如何产生:如何解决包冲突:依赖管理解决什么问题:什么是依赖范围:使用包依赖的最佳实践等 6 个问 ...
- Java 数据驱动测试
适用场景 测试搜索功能, 基于数据类型需要测多种不同的数据, 比如最大值, 小数, 负数, 字符串, 特异符号等等. 如果直接写代码, 每一种数据类型都需要写一遍代码, 冗长且不方便调试. 如果采用数 ...
- python中strip()方法学习笔记
Python strip() 方法用于移除字符串头尾指定的字符(默认为空格). 当使用strip('xxx'),只要字符串头尾有"xxx"中的一个,就会去掉,而不是符合字符串''x ...
- java解析复杂json:JSONObject 和 JSONArray的使用
在正式解析之前,我们需要下载解析Json所需要的jar包,一共有7个. 下载地址如下:https://download.csdn.net/download/zai_xia/10374080 大家也可以 ...
- ccf--20160403---路径解析
本题思路如下: 具体的细节如下:首先去掉字符串中重复出现的/,然后遇到..,就删除栈的最后一个元素,.忽略 下面是代码和题目: 问题描述 试题编号: 201604-3 试题名称: 路径解析 时间限制: ...
- 跨域访问的解决方案(非HTML5的方法:JSONP)
http://supercharles888.blog.51cto.com/609344/856886 跨域访问一直是困扰很多开发者的问题之一.因为涉及到安全性问题,所以跨域访问默认是不可以进行的,否 ...