http://acm.hdu.edu.cn/showproblem.php?pid=6578

不会做,看题解。

设dp[i][j][k][l]表示4种颜色出现的最后的位置分别是i,j,k,l的方法数,保证i>=j>=k>=l。其实不取=号,因为同一个位置不能放两个元素,除了开始的若干个比如dp[1][0][0][0]=4。

合法的转移叠加:

比如

刷新的颜色是i:dp[i+1][j][k][l]+=dp[i][j][k][l]

刷新的颜色是j:dp[i+1][i][k][l]+=dp[i][j][k][l]

刷新的颜色是k:dp[i+1][i][j][l]+=dp[i][j][k][l]

刷新的颜色是l:dp[i+1][i][j][k]+=dp[i][j][k][l]

假如从dp[i][j][k][l]转移到上述状态会导致新状态不满足约束则不进行这次转移,就太麻烦了。

由于是dp,其实只要遇到约束区间的右端点R的时候再考虑约束就可以了。

考虑四个数其实是[l,k,j,i],i肯定就是R,要是l>=L则有恰好4种颜色,否则要是k>=L则恰好3种颜色,否则要是j>=L则恰好2种颜色,否则只有1种颜色。

对每次转移后新状态的i维度必定是i+1,对i维度进行滚动节省空间。复杂度是精确的O(n4+mn3),据说很多队觉得过不了。

还卡memset???15组数据还卡memset?

#include <bits/stdc++.h>
using namespace std;
typedef long long ll; inline int read() {
int x = 0;
char c = 0;
while(c < '0' || c > '9')
c = getchar();
while(c >= '0' && c <= '9')
x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x;
} inline void _write(int x) {
if(x > 9)
_write(x / 10);
putchar(x % 10 + '0');
} inline void write(int x) {
_write(x);
putchar('\n');
} struct Condition {
int l, r, x;
bool operator<(const Condition &c)const {
return r < c.r;
}
} con[105]; const int mod = 998244353;
int n, m, dp[2][105][105][105], ctop; inline void clear0(int n) {
for(int j = 0; j <= n; ++j) {
for(int k = 0; k <= j; ++k) {
for(int l = 0; l <= k; ++l) {
dp[n & 1][j][k][l] = 0;
}
}
}
} inline void clear1(int i, int L) {
//清除==1种的
for(int j = L - 1 ; j >= 0; --j) {
for(int k = j ; k >= 0; --k) {
for(int l = k ; l >= 0; --l) {
dp[i & 1][j][k][l] = 0;
}
}
}
} inline void clear2(int i, int L) {
//清除==2种的
for(int j = i ; j >= L; --j) {
for(int k = L - 1; k >= 0; --k) {
for(int l = k ; l >= 0; --l) {
dp[i & 1][j][k][l] = 0;
}
}
}
} inline void clear3(int i, int L) {
//清除==3种的
for(int j = i ; j >= L ; --j) {
for(int k = j ; k >= L; --k) {
for(int l = L - 1; l >= 0; --l) {
dp[i & 1][j][k][l] = 0;
}
}
}
} inline void clear4(int i, int L) {
//清除==4种的
for(int j = i ; j >= L ; --j) {
for(int k = j ; k >= L ; --k) {
for(int l = k ; l >= L; --l) {
dp[i & 1][j][k][l] = 0;
}
}
}
} inline void update1(int i) {
if(ctop > m || i < con[ctop].r)
return;
while(ctop <= m && i == con[ctop].r) {
//printf("cons %d\n", ctop);
int L = con[ctop].l, x = con[ctop].x;
++ctop;
if(x == 1) {
clear2(i, L);
clear3(i, L);
clear4(i, L);
} else if(x == 2) {
clear1(i, L);
clear3(i, L);
clear4(i, L);
} else if(x == 3) {
clear1(i, L);
clear2(i, L);
clear4(i, L);
} else {
clear1(i, L);
clear2(i, L);
clear3(i, L);
}
}
} inline void update2(int i, int j, int k, int l) {
dp[(i + 1) & 1][j][k][l] += dp[i & 1][j][k][l];
if(dp[(i + 1) & 1][j][k][l] >= mod)
dp[(i + 1) & 1][j][k][l] -= mod;
dp[(i + 1) & 1][i][k][l] += dp[i & 1][j][k][l];
if(dp[(i + 1) & 1][i][k][l] >= mod)
dp[(i + 1) & 1][i][k][l] -= mod;
dp[(i + 1) & 1][i][j][l] += dp[i & 1][j][k][l];
if(dp[(i + 1) & 1][i][j][l] >= mod)
dp[(i + 1) & 1][i][j][l] -= mod;
dp[(i + 1) & 1][i][j][k] += dp[i & 1][j][k][l];
if(dp[(i + 1) & 1][i][j][k] >= mod)
dp[(i + 1) & 1][i][j][k] -= mod;
} int solve() {
ctop = 1;
memset(dp[1], 0, sizeof(dp[1]));
dp[1][0][0][0] = 4;
update1(1);
for(int i = 1; i <= n - 1; ++i) {
//printf("i=%d\n", i);
clear0(i + 1);
for(int j = i; j >= 0; --j) {
for(int k = j ; k >= 0; --k) {
if(k == j && k)
continue;
for(int l = k ; l >= 0; --l) {
if(l == k && l)
continue;
update2(i, j, k, l);
}
}
}
update1(i + 1);
for(int j = i; j >= 0; --j) {
for(int k = j; k >= 0; --k) {
if(k == j && k)
continue;
for(int l = k ; l >= 0; --l) {
if(l == k && l)
continue;
//printf("dp[%d][%d][%d][%d]=%d\n", i + 1, j, k, l, dp[(i + 1) & 1][j][k][l]);
}
}
}
//printf("\n");
}
int ans = 0;
for(int j = n - 1; j >= 0; --j) {
for(int k = j ; k >= 0; --k) {
for(int l = k ; l >= 0; --l) {
ans += dp[n & 1][j][k][l];
if(ans >= mod)
ans -= mod;
}
}
}
return ans;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int T = read();
while(T--) {
n = read(), m = read();
for(int i = 1; i <= m; ++i) {
con[i].l = read(), con[i].r = read(), con[i].x = read();
}
sort(con + 1, con + 1 + m);
write(solve());
}
return 0;
}

2019 Multi-University Training Contest 1 - 1001 - Blank - dp的更多相关文章

  1. HDU 6362.oval-and-rectangle-数学期望、微积分 (2018 Multi-University Training Contest 6 1001)

    2018 Multi-University Training Contest 6 6362.oval-and-rectangle 题意就是椭圆里画内接矩形,问你矩形周长的期望. 比赛的时候推了公式,但 ...

  2. HDU 6319.Problem A. Ascending Rating-经典滑窗问题求最大值以及COUNT-单调队列 (2018 Multi-University Training Contest 3 1001)

    2018 Multi-University Training Contest 3 6319.Problem A. Ascending Rating 题意就是给你长度为k的数列,如果数列长度k<n ...

  3. HDU 6298.Maximum Multiple-数学思维题(脑子是个好东西,可惜我没有) (2018 Multi-University Training Contest 1 1001)

    暑假杭电多校第一场,这一场是贪心场,很多贪心的题目,但是自己太菜,姿势挫死了,把自己都写吐了... 2018 Multi-University Training Contest 1 HDU6298.M ...

  4. 2019 Multi-University Training Contest 1 A.Blank(dp)

    题意:现在要你构造一个只有{0,1,2,3} 长度为n且有m个限制条件的序列 问你方案数 思路:dp[i][j][k][now]分别表示四个数最后出现的位置 最后可以滚动数组 优化一下空间 ps:我的 ...

  5. 2015 Multi-University Training Contest 1 - 1001 OO’s Sequence

    OO’s Sequence Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5288 Mean: 给定一个数列,让你求所有区间上满足 ...

  6. 2015 Multi-University Training Contest 3 1001 Magician

    Magician Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5316 Mean: n个数,2种操作,1是单点更新,2是询问区间 ...

  7. 2015 Multi-University Training Contest 4 1001 Olympiad

    代码: #include<cstdio> #include<cstring> #include<set> using namespace std; int vis[ ...

  8. 2019 Nowcoder Multi-University Training Contest 4 E Explorer

    线段树分治. 把size看成时间,相当于时间 $l$ 加入这条边,时间 $r+1$ 删除这条边. 注意把左右端点的关系. #include <bits/stdc++.h> ; int X[ ...

  9. 2019 Nowcoder Multi-University Training Contest 1 H-XOR

    由于每个元素贡献是线性的,那么等价于求每个元素出现在多少个异或和为$0$的子集内.因为是任意元素可以去异或,那么自然想到线性基.先对整个集合A求一遍线性基,设为$R$,假设$R$中元素个数为$r$,那 ...

随机推荐

  1. flask中自定义日志类

    一:项目架构 二:自定义日志类 1. 建立log.conf的配置文件 log.conf [log] LOG_PATH = /log/ LOG_NAME = info.log 2. 定义日志类 LogC ...

  2. Vuex-全局状态管理【简单小案例】

    前言: Vuex个人见解: 1.state :所有组件共享.共用的数据.理解为不是一个全局变量,不能直接访问以及操作它.2.mutations : 如何操作 state 呢?需要有一个能操作state ...

  3. 6398. 【NOIP2018模拟10.30】Generator(树状数组区间修改)

    题目描述 Description Input Output 输出 q 行,第 i 行表示数据 Di 的答案. Sample Input 4 3 2 1 1 2 4 2 1 2 1 1 3 5 2 2 ...

  4. Qt中图元对象的多重集成

    在继承自定义QGraphicsItem图元对象时,有时需要用到信号/槽机制,由于QGraphicsItem非QObject的子类 所以需要多重继承QObject,有一点需要特别注意:就是继承的顺序,一 ...

  5. 【转】DataRow复制一行到另一个DataTable

     源地址:http://www.cnblogs.com/pains/archive/2007/11/22/969003.html   下面两个方法是DataRow复制一行到另一个DataTable的, ...

  6. Java数据结构与算法(1):线性表

    线性表是一种简单的数据类型,它是具有相同类型的n个数据元素组成的有限序列.形如如A0,A1,...,An-1.大小为0的表为空表,称Ai后继Ai-1,并称Ai-1前驱Ai. printList打印出表 ...

  7. SpringMVC传参注解@RequestParam,@RequestBody,@ResponseBody,@ModelAttribute

    参考文档:https://blog.csdn.net/walkerjong/article/details/7946109 https://www.cnblogs.com/daimajun/p/715 ...

  8. Linux驱动开发4——并发和竞态

    Linux系统处于一个高并发的运行环境,不管是系统调用还是中断都要求可重入,但是有一些系统资源处于临界区,因此,必须保证临界区资源访问的原子性. 对于临界区资源被占用时,发起访问的进程,有三种处理方法 ...

  9. Gradle 编译加速

    参考:http://www.jianshu.com/p/200d55b4d40a http://blog.isming.me/2015/03/18/android-build-speed-up/ ht ...

  10. 三十三、python中configparser配置文件相关操作

    配置文件ini [a1]age = 18sex = 'man' [a2]age = 19sex = 'woman'name = False 1.对配置文件进行操作 import configparse ...