牛客国庆day3

本文探讨了一种高效的算法,通过线段树结构在给定序列中找到满足特定条件的子序列和,即在a[i]之前且小于a[i]的元素之和。两种解决方案对比,包括权值线段树和二分查找结合set的简化方法。

Leftbest

给定一个序列,如果在 a i a_i ai之前有 a j < a i a_j<a_i aj<ai,那么找到最小的 a j a_j aj,把所有这样的 a j a_j aj相加。

4 
2 1 4 3

例如样例就是1前面的2,加上3前面的4。答案为6。

比赛的时候只想到了权值线段树解法,离散化之后维护区间最小值:

struct node
{
    int l, r, k, minn;
} tr[400040];

inline void update(int k)
{
    tr[k].minn = min(tr[k * 2].minn, tr[k * 2 + 1].minn);
}

void build(int k, int l, int r)
{
    tr[k].l = l;
    tr[k].r = r;
    if (l == r)
    {
        tr[k].minn = INF;
        return;
    }
    int mid = l + r >> 1;
    build(k * 2, l, mid);
    build(k * 2 + 1, mid + 1, r);
    update(k);
}

void insert(int k, int w)
{
    if (tr[k].l == tr[k].r && tr[k].l == w)
    {
        tr[k].minn = w;
        return;
    }
    int mid = tr[k].l + tr[k].r >> 1;
    if (w <= mid)
        insert(k * 2, w);
    else
        insert(k * 2 + 1, w);
    update(k);
}

int query(int k, int l, int r)
{
    if (tr[k].l == l && tr[k].r == r)
        return tr[k].minn;
    int mid = tr[k].l + tr[k].r >> 1;
    if (r <= mid)
        return query(k * 2, l, r);
    else if (l > mid)
        return query(k * 2 + 1, l, r);
    else
        return min(query(k * 2, l, mid), query(k * 2 + 1, mid + 1, r));
}

int b[100010];
int c[100010];
int a2[100010];
int b2[100010];
struct node2
{
    int a, c;
    bool operator<(node2 temp) const
    {
        return c < temp.c;
    }
} p[100010];

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", &p[i].a), b[i] = p[i].a;
    sort(b + 1, b + 1 + n);
    int len = unique(b + 1, b + 1 + n) - b;
    for (int i = 1; i <= n; i++)
        c[i] = p[i].c = lower_bound(b + 1, b + 1 + n, p[i].a) - b;
    sort(p + 1, p + 1 + n);
    for (int i = 1; i <= n; i++)
    {
        a2[i] = p[i].a;
        b2[i] = p[i].c;
    }
    build(1, 1, 100005);
    long long ans = 0;
    for (int i = 1; i <= n; i++)
    {
        insert(1, c[i]);
        int temp = query(1, c[i] + 1, 100005);
        if (temp == INF)
            continue;
        int pos = lower_bound(b2 + 1, b2 + 1 + n, temp) - b2;
        ans += a2[pos];
    }
    printf("%lld\n", ans);
    return 0;
}

码量挺大的,看到他们的过题速度就知道事情不简单,其实直接用set存前面所有数,二分查找即可:

set<int> st;
int main()
{
    int n;
    long long ans = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        int temp;
        scanf("%d", &temp);
        if (st.upper_bound(temp) != st.end())
            ans += *st.upper_bound(temp);
        st.insert(temp);
    }
    printf("%lld\n", ans);
    return 0;
}

Flowers

n n n种花,每种花有 a i a_i ai种, m m m种不同的话可以组成一束花,问最多可以组成多少种花。

赛时用一个小顶堆一个大顶堆维护第k大,wa+tle七发之后瞎猜了一个结论改改过了。赛后发现别人都是二分,(明天一定补。

priority_queue<int, vector<int>, greater<int>> q1;
priority_queue<int> q2;
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        while (q1.size())
            q1.pop();
        while (q2.size())
            q2.pop();
        int n, m;
        read(n);
        read(m);
        for (int i = 1; i <= n; i++)
        {
            int temp;
            read(temp);
            q1.push(temp);
        }
        if (m > n)
        {
            printf("0\n");
            continue;
        }
        while (q1.size() > m)
        {
            int temp = q1.top();
            q1.pop();
            q2.push(temp);
        }
        long long ans = 0;
        while (q1.top() > 1)
        {
            int k = q1.top() - 1;
            ans += k;
            while (q1.size())
            {
                int temp = q1.top();
                q1.pop();
                temp -= k;
                q2.push(temp);
            }
            while (q1.size() < m)
            {
                int temp = q2.top();
                q2.pop();
                q1.push(temp);
            }
        }
        while (q1.top())
        {
            int k = q1.top();
            ans += k;
            while (q1.size())
            {
                int temp = q1.top();
                q1.pop();
                temp -= k;
                q2.push(temp);
            }
            while (q1.size() < m)
            {
                int temp = q2.top();
                q2.pop();
                q1.push(temp);
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}
考虑柔性负荷的综合能源系统低碳经济优化调度【考虑碳交易机制】(Matlab代码实现)内容概要:本文围绕“考虑柔性负荷的综合能源系统低碳经济优化调度”展开,重点研究在碳交易机制下如何实现综合能源系统的低碳化与经济性协同优化。通过构建包含风电、光伏、储能、柔性负荷等多种能源形式的系统模型,结合碳交易成本与能源调度成本,提出优化调度策略,以降低碳排放并提升系统运行经济性。文中采用Matlab进行仿真代码实现,验证了所提模型在平衡能源供需、平抑可再生能源波动、引导柔性负荷参与调度等方面的有效性,为低碳能源系统的设计与运行提供了技术支撑。; 适合人群:具备一定电力系统、能源系统背景,熟悉Matlab编程,从事能源优化、低碳调度、综合能源系统等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究碳交易机制对综合能源系统调度决策的影响;②实现柔性负荷在削峰填谷、促进可再生能源消纳中的作用;③掌握基于Matlab的能源系统建模与优化求解方法;④为实际综合能源项目提供低碳经济调度方案参考。; 阅读建议:建议读者结合Matlab代码深入理解模型构建与求解过程,重点关注目标函数设计、约束条件设置及碳交易成本的量化方式,可进一步扩展至多能互补、需求响应等场景进行二次开发与仿真验证。
11-08
牛客是一个专注于IT领域的在线学习和求职平台。它为广大IT从业者和学习者提供了丰富的资源和多样化的功能。 从引用中可知,牛客有练习赛和算法题目相关内容。牛客练习赛会提供不同类型的算法题目,如牛客练习赛123包含了“A.炸鸡块哥哥的粉丝题”和“B.智乃想考一道鸽巢原理”等题目,用户可以通过编写代码来解决这些题目,以此锻炼自己的算法能力和编程技巧。示例代码使用了C++语言解决“A.炸鸡块哥哥的粉丝题”: ```cpp #include<bits/stdc++.h> using namespace std; int n; string s; int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>n>>s; for(int i=0;i<(n+1)/2;i++) cout<<s[i]; return 0; } ``` 牛客也有算法题的在线评测系统,用户提交代码后,系统会根据预先设定的测试用例对代码进行评测,判断代码是否能正确解决问题。 在功能方面,牛客提供了丰富的算法题库,涵盖了各种难度和类型的题目,帮助用户提升编程和算法能力。它还提供不同语言的支持,例如引用中的C++和Java,方便不同语言背景的用户使用。此外,牛客还有求职相关的板块,为求职者提供企业招聘信息、面经、笔试题等,帮助他们更好地准备求职。 使用方法上,用户首先需要注册并登录牛客账号。之后可以在练习赛板块参与比赛,或者在题库中选择自己感兴趣的题目进行练习。对于算法题目,用户可以在代码编辑区域编写代码,选择合适的编程语言,然后提交代码进行评测。以解决“每日温度”问题的Java代码为例: ```java import java.util.*; /** * NC208 每日温度 * @author d3y1 */ public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 每日温度 * @param dailyTemperatures int整型一维数组 * @return int整型一维数组 */ public int[] temperatures (int[] dailyTemperatures) { int n = dailyTemperatures.length; int[] results = new int[n]; Stack<Integer> stack = new Stack<>(); // Deque<Integer> stack = new ArrayDeque<>(); // Deque<Integer> stack = new LinkedList<>(); for(int i=n-1; i>=0; i--){ // 单调栈 单调减(从右向左遍历) while(!stack.isEmpty() && dailyTemperatures[stack.peek()]<=dailyTemperatures[i]){ stack.pop(); } // if(stack.isEmpty()){ // results[i] = 0; // }else{ // results[i] = stack.peek()-i; // } results[i] = stack.isEmpty() ? 0 : stack.peek()-i; stack.push(i); } return results; } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hesorchen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值