【HDU4991】树状数组
http://acm.hdu.edu.cn/showproblem.php?pid=4991
用f[i][j] 表示 前i个数以第i个数结尾的合法子序列的个数,则递推式不难写出:
f[i][j] = sum(f[k][j - 1]); 其中 k < i, 且a[k] < a[i]; 边界:f[i][1] = 1; 显然需要用数据结构来优化查询
如果不考虑离散的话,用一个数据结构,记录节点为a[i]的f值,同时维护一个区间f值之和,那么f[i][j] = query(0, a[i] - 1);然后考虑特定的顺序用f值更新数据结构中的信息
具体见代码(树状数组):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <stack>
#include <string>
#define mem0(a) memset(a, 0, sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define lr rt << 1
#define rr rt << 1 | 1
#define eps 0.0001
#define lowbit(x) ((x) & -(x))
#define memc(a, b) memcpy(a, b, sizeof(b))
typedef char Str[];
using namespace std;
#define LL long long
#define DL double map<int, int> Hash;
int mol = ;
int a[], f[][], b[], R[], c[], N, n, m; void init()
{
sort(a + , a + + n);
N = ;
for(int i = ; i <= n; i++) {
if(a[i] == a[i - ] && i > ) continue;
Hash[a[i]] = ++N;
}
}
int query(int p)
{
int ans = ;
while(p) {
ans += c[p];
if(ans >= mol) ans -= mol;
p -= lowbit(p);
}
return ans;
}
void update(int p, int x)
{
while(p <= N) {
c[p] += x;
if(c[p] >= mol) c[p] -= mol;
p += lowbit(p);
}
}
int main()
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
while(~scanf("%d%d", &n, &m)) {
for(int i = ; i <= n; i++) {
scanf("%d", a + i);
}
memc(b, a);
init();
mem0(f);
//puts("d");
for(int i = ; i <= n; i++) f[i][] = ;
for(int i = ; i <= n; i++) R[i] = Hash[b[i]];
for(int j = ; j <= m; j++) {
mem0(c);
for(int i = ; i <= n; i++) {
f[i][j] = query(R[i] - );
update(R[i], f[i][j - ]);
//cout<< i<< " "<< j<< " "<< f[i][j]<< endl;
}
}
int ans = ;
for(int i = m; i <= n; i++) {
ans += f[i][m];
if(ans >= mol) ans -= mol;
}
cout<< ans<< endl;
}
return ;
}
另外用线段树写了一下, 不过超时(2000+ms)了,线段树才不到500ms,由此可见能用树状数组决不用线段树,递归线段树常数太大了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <stack>
#include <string>
#define mem0(a) memset(a, 0, sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define lr rt << 1
#define rr rt << 1 | 1
#define eps 0.0001
#define lowbit(x) ((x) & -(x))
#define memc(a, b) memcpy(a, b, sizeof(b))
typedef char Str[];
using namespace std;
#define LL long long
#define DL double
struct seg{
int sum;
}tree[ << ];
map<int, int> Hash;
int mol = ;
int a[], f[][], b[], R[], N, n, m; void init()
{
sort(a + , a + + n);
N = ;
for(int i = ; i <= n; i++) {
if(a[i] == a[i - ] && i > ) continue;
Hash[a[i]] = ++N;
}
}
void build(int l, int r, int rt)
{
tree[rt].sum = ;
if(l == r) return;
int m = (l + r) >> ;
build(lson);
build(rson);
}
void pushUP(int rt)
{
tree[rt].sum = tree[rt << ].sum + tree[rt<< | ].sum;
if(tree[rt].sum >= mol) tree[rt].sum -= mol;
}
void update(int p, int x, int l, int r, int rt)
{
if(l == r) {
tree[rt].sum += x;
if(tree[rt].sum >= mol) tree[rt].sum -= mol;
return;
}
int m = (l + r) >> ;
if(p <= m) update(p, x, lson);
else update(p, x, rson);
pushUP(rt);
}
int query(int L, int R, int l, int r, int rt)
{
if(L <= l && r <= R) {
return tree[rt].sum;
}
int m = (l + r) >> , res = ;
if(L <= m) res+= query(L, R, lson);
if(R > m) res += query(L, R, rson);
if(res >= mol) res -= mol;
return res;
}
int main()
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
while(~scanf("%d%d", &n, &m)) {
for(int i = ; i <= n; i++) {
scanf("%d", a + i);
}
memc(b, a);
init();
mem0(f);
//puts("d");
for(int i = ; i <= n; i++) f[i][] = ;
for(int i = ; i <= n; i++) R[i] = Hash[b[i]];
for(int j = ; j <= m; j++) {
build(, N, );
for(int i = ; i <= n; i++) {
if(R[i] > ) f[i][j] = query(, R[i] - , , N, );
update(R[i], f[i][j - ], , N, );
}
}
int ans = ;
for(int i = m; i <= n; i++) {
ans += f[i][m];
if(ans >= mol) ans -= mol;
}
cout<< ans<< endl;
}
return ;
}
【HDU4991】树状数组的更多相关文章
- hdu4991 树状数组+dp
这题说的是给了一个序列长度为n 然后求这个序列的严格递增序列长度是m的方案有多少种,如果用dp做那么对于状态有dp[n][m]=dp[10000][100],时间复杂度为n*m*n接受不了那么想想是否 ...
- HDU4991 Ordered Subsequence (树状数组优化DP)
dp[i][j]表示以a[i]结尾的长度为j的上升子序列个数. 方程:dp[i][j]=sum(dp[k][j-1]),a[k]<a[i],1<=k<i. 求解目标:sum(dp[k ...
- BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2221 Solved: 1179[Submit][Sta ...
- bzoj1878--离线+树状数组
这题在线做很麻烦,所以我们选择离线. 首先预处理出数组next[i]表示i这个位置的颜色下一次出现的位置. 然后对与每种颜色第一次出现的位置x,将a[x]++. 将每个询问按左端点排序,再从左往右扫, ...
- codeforces 597C C. Subsequences(dp+树状数组)
题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standar ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]
3529: [Sdoi2014]数表 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1399 Solved: 694[Submit][Status] ...
- BZOJ 3289: Mato的文件管理[莫队算法 树状数组]
3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 2399 Solved: 988[Submit][Status][Di ...
- 【Codeforces163E】e-Government AC自动机fail树 + DFS序 + 树状数组
E. e-Government time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...
随机推荐
- PHP函数:fopen
fopen() - 打开文件或者 URL. 注意:array_key_exists() 仅仅搜索第一维的键. 多维数组里嵌套的键不会被搜索到. 说明: fopen ( string $filenam ...
- Java 多线程 -- volatile 山寨版的synchronized
在 多线程中,每个线程会把数据从主内存中拷贝到自己的工作内存中,当线程完成计算后,再把工作内存的数据更新到主内存中,或者当主内存主数据有更新是,线程会去主内存取最新数据.但是,当线程特别忙时,就不会去 ...
- LeetCode466. Count The Repetitions
题目链接 传送门 题意 定义一个特殊的串, 现在给出串S1和S2的参数, 问: S2最多可以多少个连接起来扔是S1的子序列, 求出这个最大值 解题思路 注意s1与S1的区别, 可以去看题目描述, 预处 ...
- CSS中“~”(波浪号)、“,”(逗号)、“+”(加号)、“>”(大于号)、“ ”(空格)详解
“~”:$('pre ~ brother')表示获取pre节点的后面的所有兄弟节点,相当于nextAll()方法: “+”:$('pre + nextbrother')表示获得pre节点的下一个兄弟节 ...
- Redis来限制用户 ------------IP某个时间段内访问的次数
$redis = new Redis(); $redis->connect('127.0.0.1', 6379); //获取客户端真实ip地址 function get_real_ip(){ s ...
- How to use QueryPerformanceCounter? (c++,不使用 .Net)
出处:https://stackoverflow.com/questions/1739259/how-to-use-queryperformancecounter 参考:https://docs.mi ...
- 动画图解Git命令
Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理,是目前使用范围最广的版本管理工具 尽管Git是一个非常强大的工具,但我认为大多数人都会同意我的说法,即它也可以 ...
- js 实现文字滚动功能,可更改配置参数 带完整版解析代码。
前言: 本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽. 本篇文章为您分析一下原生JS写文字滚动效果 需求分析: 需要 ...
- 【Linux常见命令】seq命令
seq - print a sequence of numbers seq命令用于以指定增量从首数开始打印数字到尾数,即产生从某个数到另外一个数之间的所有整数,并且可以对整数的格式.宽度.分割符号进行 ...
- material UI中withStyles和makeStyles的区别
在material UI中,withStyles和makeStyles是经常使用的两个用于封装样式的函数.对于刚使用material UI的开发者而言,可能不太清楚这两者的区别. 本文简要探究 ...