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;
}

posted @ 2020-10-27 20:34  xchi  阅读(70)  评论(0编辑  收藏  举报