首页 > 其他分享 >CSP模拟52联测14 C.天竺葵

CSP模拟52联测14 C.天竺葵

时间:2023-10-11 21:35:33浏览次数:38  
标签:return fu int mid 52 天竺葵 ans dp 14

CSP模拟52联测14 C.天竺葵

目录

题目大意

给定两个长度为 \(n\) 的序列 \(a , b\)

需要在 \(a\) 序列中好到最长的序列 \(c\) 满足 \(c _{i + 1} > b_i \times c_i\)

输出长度

\(1\le n\le 10^6\)

思路

感觉和 \(n(\log n)\) 求最长上升子序列差不多

考虑 \(dp\)

设 \(dp_i\) 为第 \(c_i\) 的最小值

朴素的转移是 \(O(n^2)\) 的

70分代码

#include <bits/stdc++.h>
#define fu(x , y , z) for(int x = y ; x <= z ; x ++)

#define LL long long

using namespace std;
const int N = 1e6 + 5;
const LL inf = 1e12 + 5;
int n , ans , ans1 , lis[N] , len;
LL f[N] , a[N] , b[N] , min1;
int fans (int l , int r , LL x) {
    if (l == r) {
        return a[lis[l]] > x ? l : inf;
    }
    else {
        int mid = l + r >> 1;
        if (a[lis[mid]] >= x) return min (mid , fans (l , mid , x));
        else return fans (mid + 1 , r , x);
    }
}
int main () {
    freopen ("C.in" , "r" , stdin);
    freopen ("C.out" , "w" , stdout);
    int flg = 0 , x;
    scanf ("%d" , &n);
    fu (i , 1 , n) scanf ("%lld" , &a[i]);
    fu (i , 1 , n) {
        scanf ("%lld" , &b[i]);
        if (b[i] != 1) flg = 1;
    }
    if (!flg) {
        lis[len = 1] = 1;
        fu (i , 2 , n) {
            if (a[lis[len]] < a[i]) {
                lis[++len] = i;
                continue;
            }
            x = fans (1 , len , a[i]);
            lis[x] = i; 
        }
        printf ("%d" , len);
        return 0;
    }
    ans = 1 , f[1] = a[1];
    min1 = a[1];
    fu (i , 2 , n) f[i] = 1e12 + 5;
    fu (i , 2 , n) {
        ans1 = 0;
        fu (j , 1 , ans + 1) {
            if (a[i] > f[j - 1] * b[j - 1]) {
                f[j] = min (f[j] , a[i]);
                ans1 = max(ans1 , j);
            }
        }
        min1 = min (min1 , a[i]);
        ans = max (ans , ans1);
    }
    printf ("%d" , ans);
    return 0;
}

我们发现是转移的时候太慢了。

假设当前要处理的是 \(a_i\)

我们把现在的 \(dp\) 分成两部分前 \(k\) 个是小于 \(a_i\) 的,后 \(k\) 个是大于 \(a_i\) 的

因为 \(dp_{1\to k} \le a_i\) ,所以 $min_{j = 1 }^k (dp_j ,a_i)= dp_i $

因为 \(dp_{k + 1 \to len} > a_i\) ,所以 \(a_i < dp_j *b_j (j\in[k + 1 , len])\)

所以现在要更新的就只有 \(dp_k\)

直接遍历一遍,二分查找 \(k\) 就好了

时间复杂度 \(O(n\log n)\)

code

#include <bits/stdc++.h>
#define fu(x , y , z) for(int x = y ; x <= z ; x ++)
#define LL long long
using namespace std;
const int N = 1e7 + 5;
const LL inf = 1e12 + 5;
int n , ans , ans1 , lis[N] , len;
__int128 f[N] , a[N] , b[N] , min1;
int fans (int l , int r , LL x) {
    if (l == r) {
        return a[lis[l]] > x ? l : inf;
    }
    else {
        int mid = l + r >> 1;
        if (a[lis[mid]] >= x) return min (mid , fans (l , mid , x));
        else return fans (mid + 1 , r , x);
    }
}
int main () {
    freopen ("C.in" , "r" , stdin);
    freopen ("C.out" , "w" , stdout);
    LL x;
    scanf ("%d" , &n);
    fu (i , 1 , n) scanf ("%lld" , &x) , a[i] = x;
    fu (i , 1 , n) scanf ("%lld" , &x) , b[i] = x;
    int k;
    ans = 1 , f[1] = a[1];
    min1 = a[1];
    fu (i , 2 , n) {
        k = lower_bound(f + 1 , f + ans + 1 , a[i]) - f - 1;
        if (k == ans) {
            if (a[i] > b[ans] * f[ans]) f[++ans] = a[i];
        }
        else {
            if (a[i] > b[k] * f[k]) f[k + 1] = a[i];
        }
    }
    printf ("%d" , ans);
    return 0;
}

标签:return,fu,int,mid,52,天竺葵,ans,dp,14
From: https://www.cnblogs.com/2020fengziyang/p/17758246.html

相关文章

  • 144-9
    链式存储的二叉树,交换左右结点位置递归#include<stdio.h>#include<stdlib.h>#defineMaxSize100typedefstructnode{intdata;structnode*lchild,*rchild;}TreeNode,*Tree;voidCreateTree(Tree&T){intx;scanf("%d",&x)......
  • CSP模拟52 & A 层联测 9
    2023NOIPA层联测9长春花观察大样例可以发现,函数\(f(x)\)的值很小,那么可以考虑暴力枚举。用一个桶存一下平方数对\(p\)取模的值是否存在,那么可以选择从小到大枚举\(a\),找到第一个存在的\(b\)。紫罗兰考虑什么情况下会出现环,当两个点已经连通时,再在这两个点之间加一......
  • 143-8
    二叉树采用二叉链表存储,计算给定二叉树的所有双分支结点个数递归思想当根结点不存在左右结点时,return0;当根节点存在左右结点时,returnCount(T->lchild)+Count(T->rchild)+1;当根节点只存在一个结点时,returnCount(T->lchild)+Count(T->rchild);#include<stdio.h>#include......
  • 143-7
    树结点由二叉链表存储,判定给定的树是否是完全二叉树用到了辅助队列只要出队的结点非空,就将其左右结点入队,无论左右结点是否为空。若出队的结点为空,就让队列结点依次出队,若存在非空结点,就说明树不是完全二叉树。#include<stdio.h>#include<stdlib.h>#defineMaxSize100......
  • CS144-lab3
    Checkpoint3Writeup该lab主要实现TCP发送方,细节比较多,具有一定难度,编写时需要从整体上理清设计思路,然后再实现具体的函数。Timer由于要实现TCP中的超时重传功能,所以需要在发送方维护一个定时器,但不需要自己使用计时函数,因为文档里说明了所有对时间的了解都是通过tick函数得到......
  • 2023NOIP A层联测9 T3 天竺葵
    2023NOIPA层联测9T3天竺葵题面及数据范围Ps:连接为accoderOJ。看题大概是一个最长上升子序列的带权版本,于是想到dp。设\(dp[i][j]\)为到第\(i\)项,选出\(j\)个数的\(c_j\)最小值,不难想到转移:\[dp[i][j]=\min(dp[i-1][j],a[i]\(a[i]>dp[i-1][j]*b[j])\)\]若任意......
  • NOIP A层联测9 & CSP模拟52
    我的评价是三道傻逼题和一道牛逼题。T4上厕所时想了个奇怪东西打了一个半个小时170行结果剩10分钟发现假了,最后\(k=1\)都没来得及写就直接交了暴力。没想到HZOJ过了50pts,喜了。但是Accoders上只过了35pts,恼了。T1长春花\(b^2\bmodp=(b\bmodp)^2\bmodp\),所以......
  • 【面试题】JS的14种去重方法,看看你知道多少(包含数组对象去重)
    前言JavaScript数组是一种特殊的对象,用于保存多个值在一个连续的内存空间中,也正是因为如此,我们在数组中存储大量数据,但是巨大的数据量难免会有重复的,但我们并不需要重复的数据,这个时候就需要就数组进行去重,来达到每个数组都是唯一的,这样的数据才是我们想要的。数组中值类型数据去重......
  • .NET 8 RC 2 发布,将在11月14日发布正式版
    微软2023-10-10发布了.NET8RC2,下一站是.NET8正式发布,就在下个月NetConf2023[1](11月14日)期间正式发布,我们也开始筹备第四届中国.NET开发者峰会了。经过长达一年时间的开发,.NET8规划的所有主要的新功能都已推出,.NET8及其所有组件现在距离正式发布还有一个月的时间,接下......
  • 14.1 Socket 套接字编程入门
    Winsock是Windows操作系统上的套接字API,用于在网络上进行数据通信。套接字通信是一种允许应用程序在计算机网络上进行实时数据交换的技术。通过使用Windows提供的API,应用程序可以创建一个套接字来进行数据通信。这个套接字可以绑定到一个端口,以允许其他应用程序连接它。另外,Winsoc......