URAL1523(dp+树状数组)
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=41224#problem/B
分析:可以设dp[i][j]表示以i结尾长度为j的子序列的个数,那么更新就是dp[i][j]=∑dp[k][j-1],其中k<i,而且a[k]>a[i]。而要更新dp值,可以用树状数组维护,按顺序插入序列值,那么树状数组的值就可以表示比它小的长度为j-1的所有子序列的和,这样就可以在logn的时间更新dp值了,所以总复杂度是O(n*k*logn)
树状数组有两种用途(以一维树状数组举例):
1.单点更新,区间查询(即求和)
单点更新时,是往树根(即c[n])拓展
而区间查询时,是往叶子节点(即c[1])拓展
2.区间更新,单点查询
区间更新时,是往叶子节点(即c[1])拓展
单点查询时,往树根(即c[n])拓展
这两个操作只不过是在update()和sum()方法中的+和-替换一下而已。
下面解释一下“区间更新时,是往叶子节点(即c[1])拓展” 和 “单点查询时,往树根(即c[n])拓展” 的原因
举例说明吧:
c[1]=a[1];
c[2]=a[1]+a[2];
c[3]=a[3];
c[4]=a[1]+a[2]+a[3]+a[4];
c[5]=a[5];
c[6]=a[5]+a[6];
c[7]=a[7];
c[8]=a[1]+...+a[8];
假如我要更新区间[3,7],那么我首先更新[1,7],即该区间+1;再更新[1,2],该区间-1:
由于更新时往叶子节点拓展的,所以更新[1,7]时:c[7]++,c[6]++,c[4]++。
可以发现,这三个正好包含了a[1]~a[7]一次,相当于a[1]~a[7]都更新一遍 而更新[1,2]时:c[2]--,包含了a[1],a[2]。
那么当我查询某一值a[i],由于是往根节点拓展,所以每个包含a[i]的c[j]都会遇到一次(更新时每个a[i]变化一次),
即之前凡是更新过的值我都会加上。
如我想查询a[2],那么a[2]=c[2]+c[4]+c[8]=-1+1+0=0;
查询a[3],那么a[3]=c[3]+c[4]+c[8]=0+1+0=1。
1)树状数组区间更新,单点求值方法
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define M 1000000000
#define maxn 22222
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
int a[maxn],c[maxn];
int dp[maxn][];//dp[i][j]表示以a[i]为结尾长度为j的子序列;dp[i][j]=∑dp[k][j-1]且a[i]>a[k]
int n,k;
int lowbit(int x)
{
return x&(-x);
}
int sum(int i)
{
LL res=;
while(i<=n)
{
res=(res+c[i])%M;
i+=lowbit(i);
}
return res;
}
void update(int i,int x)
{
while(i)
{
c[i]=(c[i]+x)%M;
i-=lowbit(i);
}
}
int main()
{
while(scanf("%d%d",&n,&k)>)
{
memset(dp,,sizeof(dp));
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
dp[a[i]][]=;
}
for(int i=;i<=k;i++)
{
memset(c,,sizeof(c));
for(int j=i-;j<=n;j++)
{
dp[a[j]][i]=sum(a[j]);//求长度为i以a[j]点为结束的逆序对数值
update(a[j],dp[a[j]][i-]);//更新处在0~a[j]的数逆序对+dp[a[j]][i-1]
}
}
LL ans=;
for(int i=;i<=n;i++)
{
ans=(ans+dp[a[i]][k])%M;
}
printf("%lld\n",ans);
}
}
2)树状数组单点更新,区间求值方法
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define M 1000000000
#define maxn 22222
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
int a[maxn],c[maxn];
int dp[maxn][];//dp[i][j]表示以a[i]为结尾长度为j的子序列;dp[i][j]=∑dp[k][j-1]且a[i]>a[k]
int n,k;
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int y)
{
while(x<=n)
{
c[x]=(c[x]+y)%M;
x+=lowbit(x);
}
}
int sum(int x)
{
int res=;
while(x)
{
res=(res+c[x])%M;
x-=lowbit(x);
}
return res;
}
int main()
{
while(scanf("%d%d",&n,&k)>)
{
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
dp[i][]=;
}
int res;
for(int i=,j=n;i<j;i++,j--) res=a[i],a[i]=a[j],a[j]=res;
for(int i=;i<=k;i++)
{
memset(c,,sizeof(c));
for(int j=i-;j<=n;j++)
{
dp[a[j]][i]=sum(a[j]);//求在0~a[j]比a[j]小的所在点逆序对之和
update(a[j],dp[a[j]][i-]);//更新a[j]点的逆序对
}
}
int ans=;
for(int i=;i<=n;i++) ans=(ans+dp[a[i]][k])%M;
printf("%d\n",ans);
}
return ;
}
URAL1523(dp+树状数组)的更多相关文章
- 树形DP+树状数组 HDU 5877 Weak Pair
//树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...
- bzoj 1264 [AHOI2006]基因匹配Match(DP+树状数组)
1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 793 Solved: 503[Submit][S ...
- 【bzoj2274】[Usaco2011 Feb]Generic Cow Protests dp+树状数组
题目描述 Farmer John's N (1 <= N <= 100,000) cows are lined up in a row andnumbered 1..N. The cows ...
- 奶牛抗议 DP 树状数组
奶牛抗议 DP 树状数组 USACO的题太猛了 容易想到\(DP\),设\(f[i]\)表示为在第\(i\)位时方案数,转移方程: \[ f[i]=\sum f[j]\;(j< i,sum[i] ...
- codeforces 597C C. Subsequences(dp+树状数组)
题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standar ...
- HDU 2227 Find the nondecreasing subsequences (DP+树状数组+离散化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2227 Find the nondecreasing subsequences ...
- ccpc_南阳 C The Battle of chibi dp + 树状数组
题意:给你一个n个数的序列,要求从中找出含m个数的严格递增子序列,求能找出多少种不同的方案 dp[i][j]表示以第i个数结尾,形成的严格递增子序列长度为j的方案数 那么最终的答案应该就是sigma( ...
- HDU 2838 (DP+树状数组维护带权排序)
Reference: http://blog.csdn.net/me4546/article/details/6333225 题目链接: http://acm.hdu.edu.cn/showprobl ...
- [poj3378] Crazy Thairs (DP + 树状数组维护 + 高精度)
树状数组维护DP + 高精度 Description These days, Sempr is crazed on one problem named Crazy Thair. Given N (1 ...
随机推荐
- POJ 1258-Agri-Net (Kruskal)
题目链接:Agri-Net 最小生成树水题,数组开的和题目描写叙述一样,可是就是RE,有填了个0,还好这个题用 库鲁斯卡尔 敲了一遍,发现了点问题,曾经写的库鲁卡尔模板有点问题,多写了步没用的操作,已 ...
- iOS进阶面试题----经典10道
OneV‘s Den在博客里出了10道iOS面试题,用他的话是:"列出了十个应聘Leader级别的高级Cocoa/CocoaTouch开发工程师所应该掌握和理解的技术" . 在这 ...
- Redis 与 Memcache
最近,我们看到许多使用Redis的案例,尤其是大型及先进的系统中应用的更多.事实上,我们正管理着一个新的规模庞大的Redis集群,设计该架构是为了每秒能处理上百万个事务.然而,Redis与Memcac ...
- 树状DP
紫皮,各种,非原创 树状数组在我的理解就是在决策过程中具有层次关系,像是树一样,具有上下级关系或者上级对上级一定程度的限制条件 uva 12186 工人的请愿书 下属中不小于 T% 的人签字时会签字递 ...
- DBA 应该要注意Linux 环境下的一些操作
DBA 对OS的依赖.一丁点儿也不亚于DB.对于Oracle DBA.尤为突出 DB和OS的感情也与日俱增.耦合度高的让人一度以为这两要劳燕双飞了 例如.Oracle里面. 而且.故障诊断以及 ...
- Swift - 实现点击UITableView单元格时自动展开单元格
下面是一个列表单元格cell的折叠展开效果的demo.当点击单元格时会展开该单元格,便于显示一些详情什么的.点击其他单元格原来的会关闭,同时有动画效果. 效果如如下: 代码如下: 1 2 3 4 ...
- String 中的秘密
Navigation: 数据类型相关 > Delphi 的字符及字符串 > [3] - String 中的秘密 //String 的指针地址及实际的内存地址 var str: str ...
- 几本不错的CPU设计以及VLSI的书籍
1. Microprocessor Design Principales and Practrices with VHDL 特点:电路与VHDL一一对应,比较清楚,而且还用MAX+plus进行仿真 ...
- (WinForm)文件夹状态监控,最小化到托盘,开机自启动
原文 (WinForm)文件夹状态监控,最小化到托盘,开机自启动 . 文件夾監控(監測文件夾中的文件動態): //MSDN上的例子 public class Watcher { public stat ...
- c#1所搭建的核心基础之委托
本文将对c#1的委托进行详细探索 委托(delegate) 注 delegate:vt.委派代表; 授权给; [法律]债务转移; 委托作用:在恰当的时间执行一系列操作 1.简单委托的构成 声明委 ...