您的位置:首页 > 理论基础 > 计算机网络

http://acm.hdu.edu.cn/showproblem.php?pid=2227 dp + 线段树

2010-08-25 17:10 459 查看
/*
*  说什么好呢?对于这个题目写了好几天 感觉 dp + 线段树 总有道关卡,一直突破不了,总是在漫无边际的沼泽挣扎
*  因为这样心情严重受挫
*  区间的维护总是很难跟dp 联系在一起,单单的区间维护是会的,但是感觉牵扯上了dp,就什么都不会了,dp 。。一个字,怕
*  或许挣扎就是收获吧,渐渐地应该学会如何取分析问题,如何看待wrong
*  一开始敲代码的时候。我就是完全没有理解题目,想当然的理解题目是一个悲剧阿
*
*  题目求的是一个序列中非递减的所有序列组合的和
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define L int
#define LL(x) ((x) << 1)
#define RR(x) ((x) << 1 | 1)
using namespace std;
const int N = 100005;
const int mod = 1000000007;
struct Seg_tree {
int l, r;
L sum;
int mid() {
return (l + r) >> 1;
}
} tree[3 * N];
int pos
;
int df1
;
int df2
;
L dp
;
inline void Build(int l, int r, int node) {
tree[node].l = l;
tree[node].r = r;
tree[node].sum = 0;
if (l == r)
return;
int mid = (l + r) >> 1;
Build(l, mid, LL(node));
Build(mid + 1, r, RR(node));
}
inline void Update(int dx, int node, int sum) {
if (tree[node].l == tree[node].r && tree[node].l == dx) {
tree[node].sum =(tree[node].sum  + sum) % mod;  // 这里不加mod wrong,一个区间要保证在mod的范围
return;
}
/*
if (tree[node].sum != -1) {
tree[LL(node)].sum = tree[RR(node)].sum = tree[node].sum;
tree[node].sum = -1;
}
*/
int mid = tree[node].mid();
if(dx <= mid)
Update(dx, LL(node), sum);
else
Update(dx, RR(node), sum);
/*
if (r <= mid) {
Update(l, r, LL(node), sum);
} else if (l > mid) {
Update(l, r, RR(node), sum);
} else {
Update(l, mid, LL(node), sum);
Update(mid + 1, r, RR(node), sum);
}
*/
tree[node].sum = (tree[LL(node)].sum + tree[RR(node)].sum) % mod; // 区间维护
}
inline int Query(int l, int r, int node) {
if (l <= tree[node].l && tree[node].r <= r) {
return tree[node].sum;
}
/*
if (tree[node].sum != -1) {
tree[LL(node)].sum = tree[RR(node)].sum = tree[node].sum;
tree[node].sum = -1;
}
*/
int mid = tree[node].mid();
if (r <= mid) {
return Query(l, r, LL(node));
} else if (l > mid) {
return Query(l, r, RR(node));
} else {
return (Query(l, mid, LL(node)) +  Query(mid + 1, r, RR(node))) % mod ;
}
}
inline int Bin(int x, int len){ // 二分
int low = 0;
int high = len - 1;
while(low <= high){
int mid = (low + high) >> 1;
if(pos[mid] == x)
return mid;
if(pos[mid] < x){
low = mid + 1;
} else{
high = mid - 1;
}
}
return -1;
}
int main() {
int n;
while(scanf("%d", &n) != EOF){
for(int i = 0; i < n; i++){
scanf("%d", &df1[i]);
df2[i] = df1[i];
}
sort(df2, df2 + n);
int len = 0;
for(int i = 0; i < n; i++){
if(i == 0 || df2[i] != df2[i - 1])
pos[len++] = df2[i];
} // 离散化
Build(0, len - 1, 1);
//memset(dp, 0, sizeof(dp));
for(int i = 0; i < n; i++){
int r = Bin(df1[i], len);
//printf("r :: %d df1[i] :: %d/n", r, df1[i]);
L sum = (Query(0, r, 1) + 1 ) % mod;
//printf("sum :: %d/n", sum);
/*
if(sum == 0){
sum = 1;
dp[r] =( dp[r] + sum) % mod;
Update(r, 1, 1);
continue;
}
*/
//dp[r] = (dp[r] + sum) % mod;
Update(r, 1,  sum);
}
printf("%d/n", Query(0, len - 1, 1));
/*// 这里太麻烦了。。。其实就是统计一个区间的和
L sum = 0;
for(int i = 0; i < len; i++){
//printf("i :: %d dp[i] :: %d/n", i, dp[i]);
sum = (sum + dp[i]) % mod;
}
printf("%d/n", sum);
*/
}
}
//9 8 5 32 1 5 4 6 2 1
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  tree query build struct