写在前面

为什么要写?因为自己学不明白希望日后能掌握。

大体思路大概是

  1. 设计一个容斥的方案,并使其贡献可以便于计算。
  2. 得出 dp 状态,然后优化以得出答案。

下列所有类似 \([l,r]\) 这样的都是离散的。

1.

\(n\) 个点,每个点有一个能选择的颜色 \(a_i\),左右相邻的点不能同色,求方案数。

如果我们使用容斥的思想,强制 \(k\) 段的颜色相同,这个限制下的方案数对答案的贡献的容斥系数就是 \((-1)^{n-k}\)。这应该是相邻颜色不同的方案数的一个非常平凡的trick。(但是我不会

可以设 \(f_i\) 表示统计到前 \(i\) 个点所容斥的答案和。枚举 \([j,i]\) 这一段强制颜色相等。

\[f_i=-\sum\limits_{j=1}^i f_{j-1}\min\limits_{j\le k\le i}a_i
\]

这个东西可以用单调栈维护一下。

注意到这个东西可以拓展到环上。把 \(a_i\) 最小的位置轮换到最前面,然后你发现 \(f_i\) 其实就是强制了 \([i+1,n]\) 和 \(1\) 的颜色相同的答案。全部加起来就好了。

    s[0] = f[0] = 1; int top = 0;
ll sum = 0;
fo(i, 1, c) {
while(top && b[stc[top]] > b[i])
sum = (sum + (ll)(s[stc[top] - 1] - (stc[top] == 1 ? 0 :
s[stc[top - 1] - 1]) + mod) * (b[i] - b[stc[top]] + mod)) % mod,
--top;
stc[++top] = i;
sum = (sum + (ll)f[i - 1] * b[i]) % mod;
f[i] = mod - sum;
s[i] = (f[i] + s[i - 1]) % mod;
}

2.

\(n\) 个点,一个区间可以覆盖 \([l_i,r_i]\) 这一段,每个区间有一个价值 \(v_i\) ,定义一种“覆盖”为每个点至少被一个区间所覆盖的方案,其价值为所有所选区间的价值积,求所有覆盖的价值之和。

考虑强制 \(k\) 个点不被覆盖,那么这种情况对答案的贡献的容斥系数就是 \((-1)^k\)。其贡献就是这些点之间的区间的乘积之和。

这样的话,设 \(f_i\) 表示 \(i\) 点被钦定,枚举 \(j\) 表示上一个钦定点,有

\[f_i=-\sum_{j=1}^{i-1}f_j \prod_{j<l_k\le r_k<i}(v_k+1)
\]

这玩意可以线段树优化!考虑线段树的每一个位置记录的是它作为 \(j\) 造成的贡献,假设现在新加入一个区间 \(k\) ,它能使 \([0,l_k)\) 的位置的贡献发生变化,乘上 \((1+v_k)\)。

#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define ll long long
#define fo(i, a, b) for(int i = (a); i <= (b); ++i)
#define fd(i, a, b) for(int i = (a); i >= (b); --i)
using namespace std;
inline void read(int &x) {
x = 0; char ch = getchar();
while(ch < '0' || ch > '9') ch = getchar();
while(ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
}
const int N = 2e5 + 10, mod = 1e9 + 7;
namespace Seg {
#define ls t << 1
#define rs ls | 1
#define mid ((l + r) >> 1)
int tr[N << 2], pro[N << 2];
inline void mul(int t, int v) {tr[t] = (ll)tr[t] * v % mod, pro[t] = (ll)pro[t] * v % mod;}
inline void push_down(int t) {
if(pro[t] > 1) {
mul(ls, pro[t]), mul(rs, pro[t]);
pro[t] = 1;
}
}
void build(int t, int l, int r) {
pro[t] = 1;
if(l == r) return;
build(ls, l, mid), build(rs, mid + 1, r);
}
void change(int t, int l, int r, int w, int v) {
tr[t] = (tr[t] + v) % mod;
if(l == r) return ;
push_down(t);
w <= mid ? change(ls, l, mid, w, v) : change(rs, mid + 1, r, w, v);
}
void update(int t, int l, int r, int fl, int fr, int v) {
if(fl <= l && r <= fr) return mul(t, v);
push_down(t);
fl <= mid && (update(ls, l, mid, fl, fr, v), 1);
fr > mid && (update(rs, mid + 1, r, fl, fr, v), 1);
tr[t] = (tr[ls] + tr[rs]) % mod;
}
int query(int t, int l, int r, int fl, int fr) {
if(fl <= l && r <= fr) return tr[t];
push_down(t);
int ret = 0;
fl <= mid && (ret = (ret + query(ls, l, mid, fl, fr)) % mod);
fr > mid && (ret = (ret + query(rs, mid + 1, r, fl, fr)) % mod);
return ret;
}
}
struct Op {
int l, r, v;
}p[N];
vector<int> q[N];
int n, m, f[N];
int main() {
freopen("gugugu.in", "r", stdin);
freopen("gugugu.out", "w", stdout);
read(n), read(m);
fo(i, 1, m) read(p[i].l), read(p[i].r), read(p[i].v), q[p[i].r].push_back(i);
Seg::build(1, 0, n);
Seg::change(1, 0, n, 0, 1);
fo(i, 1, n + 1) {
Seg::change(1, 0, n, i, f[i] = mod - Seg::query(1, 0, n, 0, i - 1));
for(auto k : q[i])
Seg::update(1, 0, n, 0, p[k].l - 1, (p[k].v + 1) % mod);
}
printf("%d\n", mod - f[n + 1]);
return 0;
}

To be continued..

关于一类容斥原理设计 dp 状态的探讨的更多相关文章

  1. HDU 4336 Card Collector (期望DP+状态压缩 或者 状态压缩+容斥)

    题意:有N(1<=N<=20)张卡片,每包中含有这些卡片的概率,每包至多一张卡片,可能没有卡片.求需要买多少包才能拿到所以的N张卡片,求次数的期望. 析:期望DP,是很容易看出来的,然后由 ...

  2. [提升性选讲] 树形DP进阶:一类非线性的树形DP问题(例题 BZOJ4403 BZOJ3167)

    转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7337179.html 树形DP是一种在树上进行的DP相对比较难的DP题型.由于状态的定义多种多样,因此解法也五 ...

  3. dp状态压缩

    dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状 ...

  4. HDU 1074 Doing Homework (dp+状态压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1074 题目大意:学生要完成各科作业, 给出各科老师给出交作业的期限和学生完成该科所需时间, 如果逾期一 ...

  5. hdu_4352_XHXJ's LIS(数位DP+状态压缩)

    题目连接:hdu_4352_XHXJ's LIS 题意:这题花大篇篇幅来介绍电子科大的一个传奇学姐,最后几句话才是题意,这题意思就是给你一个LL范围内的区间,问你在这个区间内最长递增子序列长度恰为K的 ...

  6. hdu 4352 数位dp + 状态压缩

    XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. HDU 1074 Doing Homework(DP状态压缩)

    题意:有n门功课需要完成,每一门功课都有时间期限以及你完成所需要的时间,如果完成的时间超出时间期限多少单位,就会被减多少学分,问以怎样的功课完成顺序,会使减掉的学分最少,有多个解时,输出功课名字典序最 ...

  8. 【bzoj1076】[SCOI2008]奖励关 期望dp+状态压缩dp

    题目描述 你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关.在这个奖励关里,系统将依次随机抛出k次宝物,每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的宝物以后也不能再 ...

  9. hdu4336 Card Collector(概率DP,状态压缩)

    In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, fo ...

随机推荐

  1. oracle 当月日历的sql

    select max(sun) sun, max(mon) mon, max(tue) tue, max(wed) wed, max(thu) thu, max(fri) fri, max(sat) ...

  2. Python @函数装饰器及用法(超级详细)

    函数装饰器的工作原理是怎样的呢?假设用 funA() 函数装饰器去装饰 funB() 函数,如下所示: #funA 作为装饰器函数 def funA(fn): #... fn() # 执行传入的fn参 ...

  3. 【Linux】【Shell】【text】sed

        sed [OPTION]...  'script'  [input-file] ...         script:             地址定界编辑命令                 ...

  4. 回溯——51. N皇后

    这一题在我刚开始拿到的时候,是一点思路都没有的,只能先分析题目的要求,即queen之间的规则: 不能同行 不能同列 不能同斜线 不能同左斜 不能同右斜 同时发现,在寻找所有可能结果的穷举过程中,传入的 ...

  5. Mysql脚本 生成测试数据

    使用: ./xie.sh -uroot -p'123456' #!/bin/bash #混合测试数据库脚本 #将创建一个single数据库,其中创建一个s1表 #如果数据库存在,将会写入数据,可以在写 ...

  6. 测试工具_webbench

    目录 一.简介 二.例子 一.简介 Webbench是知名的网站压力测试工具,能测试处在相同硬件上,不同服务的性能以及不同硬件上同一个服务的运行状况. webbench的标准测试可以向我们展示服务器的 ...

  7. ubuntu 16.04下的fastadmin安装指南

    此篇博客转载于fastadmin论坛,方便自己看转到了博客里 说明文档不多,特制作一个,方便大家交流使用Ubuntu 16.04 安装fastadmin指南本文因考虑到大多数人员,习惯性在window ...

  8. ctfshow 红包题 武穆遗书

    偶然见看到这道题,就下载了看了看.确实是我自己的逆向能力不够,逆不动.但是我似乎找到了非预期... 下载程序,ida打开,发现不对.后来发现是加了upx壳,拿软件去一下.再次ida打开. 其中buff ...

  9. 嵌入式实验一:LED灯点亮

    实验一:LED灯程序 一. 实验环境 开发机环境 ​ 操作系统:ubuntu 12.04 ​ 交叉编译环境:arm-linux-gcc 4.3.2 ​ 6410板子内核源码:linux-3.0.1 目 ...

  10. 获取登录验证码失败及前后端不同域导致session丢失问题分析记录

    前言 前两周在把兄弟公司的几个服务部署到我们公司测试环境服务器的时候又遇到了不少问题,因为是前后端分离的项目,所以这次也同样遇到了跨域问题,解决方式也跟上一回的不一样,这里就再来分析记录一下. 登录验 ...