P3870 [TJOI2009]开关 线段树入门
传送门
分析
线段树的水题,作为入门题很合适
一个区间内的所有亮着的灯打开,所有关着的灯熄灭,其实就是对区间内两个状态的数值进行交换,然后套上懒标记的线段树模版即可
### 代码
```cpp
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 18,M = 1 << N;
int a[N];
int f[M];
int w[M];
int n,m;
int main(){
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++) scanf("%d",&a[i]);
memset(f,0x3f,sizeof f);
f[0] = 1;
w[0] = m;
for(int i = 0;i < (1 << n);i++){
for(int j = 1;j <= n;j++){
if(i & (1 << (j - 1))) continue;
if(w[i] >= a[j] && f[i | (1 << (j - 1))] >= f[i]){
f[i | (1 << (j - 1))] = f[i];
w[i | (1 << (j - 1))] = max(w[i | (1 << (j - 1))],w[i] - a[j]);
}
else if(w[i] < a[j] && f[i | (1 << (j - 1))] >= f[i]){
f[i | (1 << (j - 1))] = f[i] + 1;
w[i | (1 << (j - 1))] = max(w[i | (1 << (j - 1))],m - a[j]);
}
}
}
printf("%d\n",f[(1 << n) - 1]);
return 0;
}