D. Babaei and Birthday Cake---cf629D(最长上升子序列和+线段树优化)

http://codeforces.com/problemset/problem/629/D

题目大意: 我第一反应就是求最长上升子序列和  但是数值太大了  不能直接dp求  可以用线段树优化一下

#include<stdio.h>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>

using namespace std;
const long long INF = (1LL << 60);
#define inf 0x3f3f3f3f

#define met(a,b) memset(a,b,sizeof(a))
#define N 1005000
const double pi = acos(-1.0);
#define Lson r<<1|1
#define Rson r<<1

double s[N],b[N];

struct node
{
    int L,R;
    double Max;
    int mid()
    {
        return (L+R)/2;
    }
}a[N*4];

void BuildTree(int r,int L,int R)
{
    a[r].L=L;
    a[r].R=R;
    a[r].Max=0;
    if(L==R)
        return ;
    BuildTree(Lson,L,a[r].mid());
    BuildTree(Rson,a[r].mid()+1,R);
}

double Qurry(int r,int L,int R)
{
    if(L>R)
        return 0;
    if(a[r].L == L && a[r].R==R)
    {
        return a[r].Max;
    }

    if(L>a[r].mid())
        return Qurry(Rson,L,R);
    else if(R<=a[r].mid())
        return Qurry(Lson,L,R);
    else
    {
        double m1=Qurry(Lson,L,a[r].mid());
        double m2=Qurry(Rson,a[r].mid()+1,R);
        return max(m1,m2);
    }
}

void Update(int r,int L,double ans)
{
    if(a[r].L==a[r].R && a[r].L==L)
    {
        a[r].Max=ans;
        return;
    }

    if(L>a[r].mid())
        Update(Rson,L,ans);
    else
        Update(Lson,L,ans);

    a[r].Max=max(a[Lson].Max,a[Rson].Max);
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        double r,h;
        met(b,0);
        met(s,0);
        for(int i=0;i<n;i++)
        {
            scanf("%lf %lf",&r,&h);
            s[i]=b[i]=pi*r*r*h;
        }
        sort(b,b+n);
        int len=unique(b,b+n)-b;

        BuildTree(1,0,len-1);

        double  sum=0;
        for(int i=0;i<n;i++)
        {
            int pos=lower_bound(b,b+len,s[i])-b;///找到所在的下标
            double ans=Qurry(1,0,pos-1)+s[i];///查找之前的最大值
            Update(1,pos,ans);///更新点
            sum=max(sum,ans);
        }
        printf("%.12lf\n",sum);
    }
    return 0;
}
时间: 2024-10-10 14:36:36

D. Babaei and Birthday Cake---cf629D(最长上升子序列和+线段树优化)的相关文章

HDU 1025-Constructing Roads In JGShining&#39;s Kingdom(最长不降子序列,线段树优化)

分析: 最长不降子序列,n很大o(n^2)肯定超,想到了小明序列那个题用线段树维护前面的最大值即可 该题也可用二分搜索来做. 注意问题输出时的坑,路复数后加s #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vecto

BZOJ 3904 最长上升子序列 lkids 线段树

题目大意:给定一个序列,求以较小数开始的锯齿子序列,使相邻两项之间差值不小于k 令f[i][0]表示第i个数为序列中的较大值的最长子序列 f[i][1]表示第i个数为序列中的较小值的最长子序列 暴力转移是O(n^2)的 我们发现决策点的值都是连续的一段区间 因此用线段树维护一下就行了 (真简略) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #def

18.10.9 不好做的最长上升子序列(nlogn树状数组解LIS)

描述 一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的.对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N.比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等.这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8

Codeforces 527C Glass Carving (最长连续0变形+线段树)

Leonid wants to become a glass carver (the person who creates beautiful artworks by cutting the glass). He already has a rectangular w mm ?×? h mm sheet of glass, a diamond glass cutter and lots of enthusiasm. What he lacks is understanding of what t

D. Babaei and Birthday Cake---cf629D(LIS线段树优化)

题目链接:http://codeforces.com/problemset/problem/629/D 题意就是现有n个蛋糕,蛋糕的形状是圆柱体,每个蛋糕的体积就是圆柱体的体积,每个蛋糕的编号是1---n,可以把蛋糕 i 放到蛋糕 j 上面,前提是 j<i 并且 Vj<Vi;最后求最大的体积是多少: 实质就是求上升子序列的最大和,但是由于n的范围是10w所以不能用n^2的复杂度,所以可以用线段树进行优化,时间复杂度变为nlogn: #include <iostream> #incl

HDU 6681 Rikka with Cake(扫描线、动态开点线段树)

http://acm.hdu.edu.cn/showproblem.php?pid=6681 题意 在矩形区域内有k条射线,问这些射线将矩形分成了多少区域 题解 容易发现答案为所有射线交点个数. 按y从排序扫描矩形区域,动态开点线段树维护区间内竖线的个数,由于n,m范围较大,需要离散化处理,但这样比较麻烦且此题空间足够所以建议用动态开点. 1 #define bug(x) cout<<#x<<" is "<<x<<endl 2 #defi

51nod 最长递增子序列

nlogn版最长递增子序列.线段树.(其实常数蛮大的....) #include<iostream> #include<cstring> #include<algorithm> #define maxn 50050 using namespace std; int n,ls[maxn<<2],rs[maxn<<2],val[maxn<<2],root,tot=0; struct pnt { int id,val; }p[maxn];

动态规划入门 COGS1398 最长上升子序列

1398. 最长上升子序列 ★   输入文件:lis1.in   输出文件:lis1.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] 设有整数序列A[1],A[2],A[3],-,A[m],若存在下标i1<i2<i3<-<in,且A[i1]<A[i2]<A[i3]<-<A[in],则称 序列A[1],A[2],A[3],-,A[m]中有长度为n的上升子序列A[i1] , A[i2] ,A[i3] ,-,A[in]. 请编程计算

最长上升子序列O(nlogn) 要强的T^T(2358)

题目来源:http://120.78.128.11/Problem.jsp?pid=2358 要强的T^T TimeLimit:1000MS  MemoryLimit:65536K 64-bit integer IO format:%lld Problem Description T^T看到Home_W出了一道这么简短的数学题,觉得自己肯定也能出一道.于是便有了这题: 给定n个数,只包含1和2,问最少修改几个数,能使得n个数有序(单调不减) Input 第一行包含一个数n,表示有n个数,接下来的