首页 > 其他分享 >03/10/2024 上课笔记 & 解题报告

03/10/2024 上课笔记 & 解题报告

时间:2024-03-10 22:33:18浏览次数:27  
标签:03 ch rgt 10 int 样例 2024 lft include

双向链表

前言

第一次接触这玩意儿,所以记录一下。

题目

[国家集训队] 种树

题目描述

A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。

园林部门得到指令后,初步规划出 \(n\) 个种树的位置,顺时针编号 \(1\) 到 \(n\)。并且每个位置都有一个美观度 \(A_i\),如果在这里种树就可以得到这 \(A_i\) 的美观度。但由于 \(A\) 城市土壤肥力欠佳,两棵树决不能种在相邻的位置(\(i\) 号位置和 \(i+1\) 号位置叫相邻位置。值得注意的是 \(1\) 号和 \(n\) 号也算相邻位置)。

最终市政府给园林部门提供了 \(m\) 棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将 \(m\) 棵树苗全部种上,给出无解信息。

输入格式

输入的第一行包含两个正整数 \(n\),\(m\)。

第二行 \(n\) 个整数,第 \(i\) 个代表 \(A_i\)。

输出格式

输出一个整数,表示最佳植树方案可以得到的美观度。如果无解输出 Error!

样例 #1

样例输入 #1
7 3
1 2 3 4 5 6 7
样例输出 #1
15

样例 #2

样例输入 #2
7 4
1 2 3 4 5 6 7
样例输出 #2
Error!

提示

数据编号 \(n\) 的大小 数据编号 \(n\) 的大小
\(1\) \(30\) \(11\) \(200\)
\(2\) \(35\) \(12\) \(2007\)
\(3\) \(40\) \(13\) \(2008\)
\(4\) \(45\) \(14\) \(2009\)
\(5\) \(50\) \(15\) \(2010\)
\(6\) \(55\) \(16\) \(2011\)
\(7\) \(60\) \(17\) \(2012\)
\(8\) \(65\) \(18\) \(199999\)
\(9\) \(200\) \(19\) \(199999\)
\(10\) \(200\) \(20\) \(200000\)

对于全部数据:\(m\le n\),\(-1000\le A_i\le1000\)。

题目分析。

这是一道可反悔贪心 + 双向链表的题。

  • 一、可反悔贪心
    题目中说,一个树选了旁边两个数就不能选,比如下图。
    image

我们肯定先选 \(9\),然后 \(8\)、\(8\) 不能选,所以最后答案是 \(9+1=10\)。但是这题最优解显然是 \(8+8=16\)。

我们肯定会想到用可反悔贪心,用大根堆。

但是我们无法比较,来进行反悔。

于是我们想了一个办法。第一次选 \(9\) 时将 \(8+8-9=7\) 加入这个大根堆。我们不妨来模拟一下。

首先 \(ans\) 加 \(9\),然后删去 \(8\)、\(8\), \(7\) 于队列。
image

后出 \(8\),被删了,跳过,然后就弹出 \(7\) 了,\(ans\) 加上 \(7\),把两边剔除,

image

于是答案就是 \(9+7=16\),我们发现和 \(8+8=16\) 结果一样。

  • 二、如何用双向链表删点。

image

中间的为 \(x\),我们只要让 [p[x].lft].rgt = p[x].rgt,[x].rgt].lft = p[x].lft

然后分别令 \(x\) 为 p[x].lft 和 p[x].rgt` 就行了。

代码

/*
    Author: Rainypaster(lhy)
    Time: 03/10/2024
    File: P1972.cpp
    Email: [email protected]
*/
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <bits/stdc++.h>
#define int long long
using namespace std;

namespace IO
{
    template<typename T>
    T read(T x)
    {
        T sum = 0, opt = 1;
        char ch = getchar();
        while(!isdigit(ch)) opt = (ch == '-') ? -1 : 1, ch = getchar();
        while( isdigit(ch)) sum = (sum << 1) + (sum << 3) + (ch ^ 48), ch = getchar();
        return sum * opt;
    }

}
#define read IO::read(0)
#define rep(i, n) for(int i = 1; i <= n; i ++)
#define repa(i, n) for(int i = 0; i < n; i ++)
#define repb(i, n) for(int i = 1; i <= n; i ++)
#define repc(i, n) for(int i = 0; i < n; i ++)
#define lson (u << 1)
#define rson (u << 1 | 1)
#define gcd(a, b) __gcd(a, b)

const int N = 2e5 + 5;

struct Node{
	int val,id;
	bool operator <(Node it) const{
		return val < it.val;
	}
};

priority_queue<Node> q;
struct node
{
    int val, lft, rgt;
}p[N];

bool vis[N];

int ans;

void delt(int x)
{
    p[p[x].lft].rgt = p[x].rgt;
    p[p[x].rgt].lft = p[x].lft;
}

void solve()
{
    int n = read, m = read;
    if(n / 2 < m) {
        puts("Error!");
        return ;
    }
    for(int i = 1;i <= n;i ++ ){
        p[i].val = read;
        p[i].lft = i - 1;
        p[i].rgt = i + 1;
        q.push({p[i].val, i});
    }
    p[1].lft = n, p[n].rgt = 1;

    for(int i = 1;i <= m;i ++ ){
        while(vis[q.top().id]) q.pop();
        Node now = q.top();
        q.pop();
        vis[p[now.id].lft] = vis[p[now.id].rgt] = true;
        p[now.id].val = p[p[now.id].lft].val + p[p[now.id].rgt].val - p[now.id].val;
        ans += now.val;
        q.push({p[now.id].val, now.id});
        delt(p[now.id].lft), delt(p[now.id].rgt);
    }
    cout << ans << endl;
}

signed main()
{
    int T = 1;
    while(T -- ) solve();
    return 0;
}

标签:03,ch,rgt,10,int,样例,2024,lft,include
From: https://www.cnblogs.com/Rainypaster/p/18065023

相关文章

  • 我的高考不到100天
    我的高考不到100天DAY-89修改了周末的测试,简记了解到的之前不懂的东西化学:溴水(包括溴的CCI4溶液)和液溴的区别是液溴的溴含量大于前者加成反应时大多是溴水,取代反应则是液溴(反应从易到难,溴含量随之增大)物理:对\(R=pl/s\)多了一些了解,其中的\(l\)是指电流流过的长度,\(s\)是......
  • 1005. K 次取反后最大化的数组和c
    intlargestSumAfterKNegations(int*nums,intnumsSize,intk){intt[201]={0};intsum=0;for(inti=0;i<numsSize;i++){t[100+nums[i]]++;sum+=nums[i];}while(k>0){for(inti=0;i<201;i++){......
  • 2024.3.04~2024.3.10 by manjuan
    给你一个数组a1,a2…an。请计算有多少个图元(i,j,k,l)符合以下条件:·\(1\)\(\le\)\(i\)<\(j\)<\(k\)\(<\)\(l\)\(\le\)n·a\(i\)\(=\)a\(k\)和a\(j\)\(=\)a\(l\)\(Input\)Thefirstlinecontainsasingleinteger\(t\)(\(1\)≤\(t\)......
  • vs2019单独重新安装python37_64失败解决办法(bilibili上我最早写的是https://www.bilib
    上个周末的时候,我发现用vs2019编写python的时候。代码高亮出现了奇怪的问题,进入解决方案的时候,print还是蓝色的,但是过了几秒钟后就变为黑色了,因此在最开始的时候我试图通过换一个皮肤和在管理扩展里面找扩展来解决,但是还是有相关问题。于是到vs2019对应的python文件夹找问题,目录是......
  • HNOI2024 游记
    Day0机房打摆,早上扫雷但是离xkr的记录差的有点远,很自闭。一天就写了fft和ntt。晚上有点失眠。Day1带了东鹏特饮和巧克力就去考试了。T1发现直接枚举\(m\bmodn\)的值然后解方程就行,25分钟过了大样例,然后对着代码瞪了10分钟发现没什么错误就丢掉了。T2想了一......
  • 3.10
    昨天放假回去得知我对象给我买了一个重云的吧唧,真的好可爱啊......
  • 3101: *【莫比乌斯反演:练习】gcd(i,j)=k的对数[POI2007]ZAP-Queries
    问题给出\(n,m,k\)(\(1\leqn,m,k\leq10^5\)),求\(\sum\limits_{i=1}^n\sum\limits_{j=1}^m\lbrack\gcd(i,j)=k\rbrack\),即:满足\(1\leqi\leqn\),\(1\leqj\leqm\),且\(\gcd(i,j)=k\)的二元组\((i,j)\)的数量。题解\(\sum\limits_{i=1}......
  • 2024年3月10号题解
    299.猜数游戏解题思路对出现的数字在两个数组中进行统计先计算公牛的个数,如果有那么统计的数字的数量对应减一,因为统计是用来算奶牛的数量的遍历统计数组,奶牛的数量加上两个数组中最小的值,因为是匹配,所以不可能多出来的也可以匹配,所以是加上其中的最小值代码实现intmin(i......
  • 2024.3 记录
    3.5vp了一场edu,过了四题,但是D题有*2100,自我感觉还行。这里写一下后三题的题解。CF1913DArrayCollapse数字互不相同,先上个单调栈求出每个点的支配区间。考虑dp,\(f_i\)表示只考虑\([1,i]\)时的方案数,找到最靠左的\(j\)满足\([j,i]\)间不存在小于\(p_i\)的数,那......
  • day.03 数据类型
    publicclassDemo2{publicstaticvoidmain(String[]args){//整数拓展:进制二进制0b十进制八进制0十六进制0xinti=10;inti2=010;//八进制0inti3=0x10;//十六进制0xSystem.out.println(i);System.......