codeforces 629D 树状数组+LIS

题意:n个圆柱形蛋糕,给你半径 r 和高度 h,一个蛋糕只能放在一个体积比它小而且序号小于它的蛋糕上面,问你这样形成的上升序列中,体积和最大是多少

分析:根据他们的体积进行离散化,然后建树状数组,按照序号进行循环,每次查询体积比它小的蛋糕形成的最大体积

注:因为是按照序号进行循环,所以序号一定是严格小于它的,时间复杂度O(nlogn)

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+5;
const double pi=3.14159265358;
LL c[N],a[N],h,r,o[N];
int cnt;
void update(int i,LL t)
{
   for(;i<=cnt;i+=(i&(-i)))
     c[i]=max(c[i],t);
}
LL query(int i)
{
   LL ans=0;
   for(;i>0;i-=(i&(-i)))
    ans=max(ans,c[i]);
   return ans;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
       scanf("%I64d%I64d",&r,&h);
       a[i]=o[i]=r*r*h;
    }
    sort(a+1,a+1+n);
    cnt=1;
    for(int i=2;i<=n;++i)
       if(a[i]!=a[i-1])a[++cnt]=a[i];
    LL res=0;
    for(int i=1;i<=n;++i)
    {
       int pos=lower_bound(a+1,a+1+cnt,o[i])-a;
       LL tmp=query(pos-1)+o[i];
       res=max(tmp,res);
       update(pos,tmp);
    }
    printf("%.10f\n",(double)(res)*pi);
    return 0;
}

时间: 2024-12-28 10:46:57

codeforces 629D 树状数组+LIS的相关文章

HDU 3333 | Codeforces 703D 树状数组、离散化

HDU 3333:http://blog.csdn.net/julyana_lin/article/details/7877164 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化处理一下,标记一下前面是否出现过这个值,然后不断更新last数组(该数组保存的是每个数最后一次出现的位置).最后用树状数组维护. 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4

CodeForces 396C 树状数组 + DFS

这题目一开始看到了就想到了线段树或者树状数组,但是对于一个节点的所有子节点加权有所疑惑,后来看到根树这个条件,就像到了 那么1号点肯定在第一层,那么建立单向边往下搜,然后记录一下 每一个节点所在的 层,最后 两个节点 相差的 层数就知道了,就容易加权处理了,然后就开始建立数组了,后来一直爆错,后来发现 是范围有问题,这样直接建立是错的,因为不知道具体范围,数字太大了, 所以参考了一下 http://blog.csdn.net/keshuai19940722/article/details/201

Codeforces 276E(树状数组)

题意:一棵树有n个节点,1是根节点,根节点的子节点是单链,然后现在有两种操作0 v x d表示距离节点v为d的节点权值都加x,操作1 v问v节点的权值,初始节点权值都是0. 题解:看了别人的题解才会的,维护两种树,把每条单链都当做一个树状数组维护当前链上每个节点的权值,另一种是从根节点开始维护距离为x的节点的权值. #include <cstdio> #include <cstring> #include <algorithm> #include <vector&

Encryption (hard) CodeForces - 958C3 (树状数组)

大意: 给定序列$a$, 要求将$a$分成$k$个非空区间, 使得区间和模$p$的和最小, 要求输出最小值. $k$和$p$比较小, 直接暴力$dp$, 时间复杂度是$O(nklogp)$, 空间是$O(nk+kp)$ $dp[i][j]=min(...,f[j-1][s[i]-1]+1,f[j][s[i]],f[j][s[i]+1]-1+p,...)$ 看了其他提交, 好像有$O(nk)$的做法. #include <iostream> #include <sstream> #i

【二维树状数组】【CF10D】 LCIS

传送门 Description 给你两个串,求他们的最长公共上升子序列 Input 第一行是第一个串的长度\(n\) 第二行\(n\)个数代表第一个串 第三行是第二个串的长度\(m\) 第四行\(m\)个数代表第二个串 Output 输出最长子序列的长度以及方案 Hint \(For~All:\) \(0~\leq~n~\leq~500\) Solutoin 先考虑朴素DP,可以设\(f_{i,j}\)代表第一个串选前\(i\)个,第二个串选前\(j\)个的答案,转移显然\(f_{i,j}=\m

Codeforces Round #277 E. LIS of Sequence(486E) 树状数组乱搞

http://codeforces.com/contest/486/problem/E E. LIS of Sequence time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output The next "Data Structures and Algorithms" lesson will be about Longest I

Codeforces 486E LIS of Sequence --树状数组

题意: 一个序列可能有多个最长子序列,现在问每个元素是以下三个种类的哪一类: 1.不属于任何一个最长子序列 2.属于其中某些但不是全部最长子序列 3.属于全部最长子序列 解法: 我们先求出dp1[i]表示1~i 的最长递增子序列长度, dp2[i]表示 n~i 的最长递减子序列长度(严格增减),这里我们可以用维护最大值的树状数组来解决,开始还以为要用nlogn求LIS的那种算法,当然那样应该也可以,这里元素值是1~10^5的,可以直接用树状数组,如果元素值任意的话,我们离散化一下也可以用树状数组

【Codeforces】Gym 101156E Longest Increasing Subsequences LIS+树状数组

题意 给定$n$个数,求最长上升子序列的方案数 根据数据范围要求是$O(n\log n)$ 朴素的dp方程式$f_i=max(f_j+1),a_i>a_j$,所以记方案数为$v_i$,则$v_i=v_i+v_j,(f_i=f_j+1)$,利用lis的$O(n\log n)$树状数组做法同时维护长度和方案数 从通酱博客里还看到更详尽的解释:stackoverflow 时间复杂度$O(n\log n)$ 代码 #include <bits/stdc++.h> using namespace

CodeForces 380C Sereja and Brackets(扫描线+树状数组)

[题目链接] http://codeforces.com/problemset/problem/380/C [题目大意] 给出一个括号序列,求区间内左右括号匹配的个数. [题解] 我们发现对于每个右括号,其匹配的左括号是固定的, 我们保存每个右括号匹配的左括号位置, 对区间询问进行线扫描,将扫描的区间右端点及其之前所有的右括号对应的左括号位置做标记, 只要查询询问区间的标记个数就是答案,这个可以用树状数组维护. [代码] #include <cstdio> #include <algor