FZu Problem 2236 第十四个目标 (线段树 + dp)

题目链接:

  FZu  Problem 2236 第十四个目标

题目描述:

  给出一个n个数的序列,问这个序列内严格递增序列有多少个?不要求连续

解题思路:

  又遇到了用线段树来优化dp的题目,线段树节点里面保存所表达区间里面的方案数。先离散化序列(升序排列),建树,然后按照没有sort前的顺序向线段树里面加点,每次查询小于该数的方案数目+1, 就是当前节点插入进去能影响的方案数目。在线段树对应位置加上新增加的数目即可。

  1 #include <cstdio>
  2 #include <queue>
  3 #include <stack>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <iostream>
  7 #include <algorithm>
  8 using namespace std;
  9
 10 #define lson 2*root
 11 #define rson 2*root+1
 12 typedef __int64 LL;
 13 const LL mod = 1000000007;
 14 const LL INF= 1e14+7;
 15 const int maxn = 100010;
 16
 17 struct node
 18 {
 19     int l, r;
 20     LL num;
 21     int mid ()
 22     {
 23         return (l + r) / 2;
 24     }
 25 } tree[maxn*4];
 26 LL a[maxn], b[maxn];
 27
 28 void build (int root, int l, int r)
 29 {
 30     tree[root].l = l;
 31     tree[root].r = r;
 32     tree[root].num = 0;
 33     if (l == r)
 34         return ;
 35
 36     build (lson, l, tree[root].mid());
 37     build (rson, tree[root].mid()+1, r);
 38 }
 39 void Insert (int root, LL x, int y)
 40 {
 41     if (tree[root].l == tree[root].r && tree[root].l == y)
 42     {
 43         tree[root].num =(tree[root].num + x) % mod;
 44         return ;
 45     }
 46
 47     if (tree[root].mid() >= y)
 48         Insert (lson, x, y);
 49     else
 50         Insert (rson, x, y);
 51     tree[root].num = (tree[lson].num + tree[rson].num) % mod;
 52 }
 53 LL query (int root, int l, int r)
 54 {
 55     if (tree[root].l == l && tree[root].r == r)
 56         return tree[root].num;
 57
 58     if (tree[root].mid() >= r)
 59         return query (lson, l, r);
 60     else if (tree[root].mid() < l)
 61         return query (rson, l, r);
 62     else
 63     {
 64         LL num = 0;
 65         num += query (lson, l, tree[root].mid());
 66         num += query (rson, tree[root].mid()+1, r);
 67         return num % mod;
 68     }
 69 }
 70
 71 int main ()
 72 {
 73     int n;
 74
 75     while (scanf ("%d", &n) != EOF)
 76     {
 77         for (int i=0; i<n; i++)
 78         {
 79             scanf ("%I64d", &a[i]);
 80             b[i] = a[i];
 81         }
 82
 83         sort (a, a+n);
 84         int m = unique (a, a+n) - a;
 85
 86         LL ans = 0;
 87         build (1, 0, m);
 88         for (int i=0; i<n; i++)
 89         {
 90             LL nu, tmp = lower_bound (a, a+m, b[i]) - a;
 91             if (tmp == 0)
 92                 nu = 0;
 93             else
 94                 nu = query (1, 0, tmp-1);
 95
 96             Insert (1, nu+1, tmp);
 97         }
 98
 99         printf ("%I64d\n", query (1, 0, m));
100     }
101     return 0;
102 }
103 ///4 1 2 2 3
时间: 2024-11-05 17:24:01

FZu Problem 2236 第十四个目标 (线段树 + dp)的相关文章

fzuoj Problem 2236 第十四个目标(树状数组+dp)

Problem 2236 第十四个目标  Problem Description 目暮警官.妃英里.阿笠博士等人接连遭到不明身份之人的暗算,柯南追踪伤害阿笠博士的凶手,根据几起案件现场留下的线索发现凶手按照扑克牌的顺序行凶.在经过一系列的推理后,柯南发现受害者的名字均包含扑克牌的数值,且扑克牌的大小是严格递增的,此外遇害者与毛利小五郎有关. 为了避免下一个遇害者的出现,柯南将可能遭到暗算的人中的数字按关联程度排列了出来,即顺序不可改变.柯南需要知道共有多少种可能结果,满足受害人名字出现的数字严格

Problem 2236 第十四个目标

Problem 2236 第十四个目标 Accept: 4    Submit: 6Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem Description 目 暮警官.妃英里.阿笠博士等人接连遭到不明身份之人的暗算,柯南追踪伤害阿笠博士的凶手,根据几起案件现场留下的线索发现凶手按照扑克牌的顺序行凶.在经 过一系列的推理后,柯南发现受害者的名字均包含扑克牌的数值,且扑克牌的大小是严格递增的,此外遇害者与毛利小五郎有关. 为了避免下一

FZU 2079 最大获利(线段树+DP)

Description Sean准备投资一些项目.有n个投资项目,投资第i个项目需要花费Ci元.Sean发现如果投资了某些编号连续的项目就能赚得一定的钱.现在给出m组连续的项目和每组能赚得的钱,请问采取最优的投资策略的最大获利是多少? 样例最佳策略是全部项目都投资,然后第1,2组都满足了,获利为2+2-3=1.最佳策略可能是不投资,即最大获利为0. Input 每组数据第一行输入两个整数N和M , N表示项目数,M表示能获利的连续的项目组数,1 <= N <= 20000,1 <= M

HDU6447 YJJ&#39;s Salesman 2018中国大学生程序设计竞赛 - 网络选拔赛1010 离散化+线段树+DP

YJJ's Salesman Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 253    Accepted Submission(s): 62 Problem Description YJJ is a salesman who has traveled through western country. YJJ is always on

poj3468A Simple Problem with Integers(线段树的区域更新)

http://poj.org/problem?id=3468 真心觉得这题坑死我了,一直错,怎么改也没戏,最后tjj把q[rt].lz改成了long long 就对了,真心坑啊. 线段树的区域更新. 线段树功能:update:成段增减 query:区间求和 #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> using namespace std; #d

hdu 3016 Man Down (线段树 + dp)

题目大意: 是男人就下一般层...没什么可以多说的吧. 注意只能垂直下落. 思路分析: 后面求最大值的过程很容易想到是一个dp的过程 . 因为每一个plane 都只能从左边 从右边下两种状态. 然后我们所需要处理的问题就是 ,你如何能快速知道往左边下到哪里,往右边下到哪里. 这就是线段树的预处理. 讲线段按照高度排序. 然后按照高度从小到大加入到树中. 然后去寻找左端点 和 右端点最近覆盖的线段的编号. #include <cstdio> #include <iostream> #

ZOJ3632 线段树+DP

买西瓜吃,每个西瓜有两个参数,一个是p代表价格,一个是t代表能吃几天,要求n天每天都能吃西瓜,而且如果你今天买了,以前买的还没吃完 那么都得扔了,求最小花费,还真想不到用线段树+DP,最后看了一下别人的标题,想了一下,DP方程挺好推的,线段树也只是单点查询, #include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #inclu

POJ 3468 A Simple Problem with Integers(线段树)

题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 56005   Accepted: 16903 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with

POJ3468 A Simple Problem with Integers 【线段树】+【成段更新】

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 57666   Accepted: 17546 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of