首页 > 其他分享 >2024QBXT暑假j组精英营Day2

2024QBXT暑假j组精英营Day2

时间:2024-07-16 19:18:46浏览次数:6  
标签:nx int void 元素 Day2 链表 暑假 2024QBXT 维护

\(一\) \(数据结构\)

\(1\) \(链表\)

\(1.0\) \(介绍\)

链表分为单向链表和双向链表

单向链表即当前链表只指向下一个元素

双向链表即对于每个元素,记录其前面一个元素,也记录其后面一个元
素。

链表不建议使用 STL 的某些元素进行替代,手写链表更为方便。

\(1.1\) \(单向链表\)

\(1.1.1\) \(介绍\)

维护每个元素编号,然后维护 nx 指针,表示当前元素的下
一个元素是谁加入和删除都是方便的。

\(1.1.2\) \(实现\)

//插入一个元素 
void ins(int x,int y){
	int to = nx[x];
	nx[x] = y;
	nx[y] = to;
}

//删除一个元素
void erase(int x){
	int to = nx[x];
	nx[x] = nx[to];
} 

\(1.1.3\) \(例题\)

luogu B3631 单向链表

点击查看代码

\(1.1.4\) \(前向星\)

本质上前项星是由多个单项链表组成,维护链头数组,然后可以支持每
个点加边。

struct node {
	int next;
	int to;
}e[N*2];
int cnt,h[N];
void add(int x,int y){
	cnt++;
	e[cnt] = {h[x],y};
	h[x] = cnt;
}
void dfs(int x){
	for (int i = h[x];i;i = e[i].next)
		dfs(e[i].to,x);
}

luogu p3916 图的遍历

点击查看代码(这份代码只能的60分)
using namespace std;

#define ll long long

const int N = 1e5 + 5;

int n,m;

struct node{
	int next,to;
}e[N >> 1];

int cnt,h[N];

void add(int x,int y){
	cnt ++;
	e[cnt] = {h[x],y};
	h[x] = cnt;
}

int ans[N],id;

void dfs(int x){
	if(!ans[x]) ans[x] = id;
	else return ;
	for (int i = h[x];i;i = e[i].next)
		dfs(e[i].to);
}

int main(){
	cin >> n >> m;
	for (int i = 1;i <= m;i ++){
		int a,b;
		cin >> a >> b;
		add(b,a);
	}
	
	for (int i = n;i >= 1;i --) id = i,dfs(i);
	for (int i = 1;i <= n;i ++) cout << ans[i] << " ";
	puts("");

	return 0;
}


\(1.2\) \(双向链表\)

\(1.2.1\) \(介绍\)

每个元素维护前驱 pr 和后继 nx 两个数组,可以实现动态增删的操作

\(1.2.2\) \(实现\)

void ins(int x,int y){
	int to = nx[x];
	nx[x] = x;
	pr[to] = y;
	pr[y] = x;
	nx[y] = to;
}

void era(int x){
	int L = pr[x],R = nx[x];
	nx[L] = R,pr[R] = L;
}

\(2\) \(栈\)

\(2.0\) \(介绍\)

一种结构,维护一个序列,每次从末端加入元素,然后末端弹出元素。
具体维护:使用一个数组,维护一个 tp 指针进行处理

\(2.1\) \(维护\)

手写栈:

int stk[N],tp;
void push(int x){
	stk[++tp] = x;
}
void top(){
	return stk[tp];
}
void pop(){
	tp--;
}

STL栈:

stack<int>stk;
stk.push(1);
stk.pop();
cout << stk.top() << "\n";
cout << stk.size() << "\n";

\(2.2\) \(例题\)

luogu p3618 【模板】栈

\(2.3\) \(单调栈\)

\(2.3.1\) \(介绍\)

本质上是用栈维护了单调的结构

\(2.3.1\) \(例题\)

luogu p5788 【模板】单调栈

从后往前枚举,栈内维护单调的下标,满足这些下标的值是递减的,id
也是递减的,由于满足单调的过程,我们称为单调栈。

关键性质在于保留对当前状态最优的信息。

\(3\) \(队列\)

\(3.0\) \(介绍\)

一种结构,维护一个序列,每次从末端加入元素,然后前端弹出元素。
具体维护,用一个数组,维护前端后端指针,维护加入删除。

\(3.1\) \(实现\)

手写:

int q[N],l,r;
void push(int x){
	q[++r] = x;
}
int front(){
	return q[1];
}
void pop(){
	l++;
}

STL:

queue<int>q;
q.push(1);
q.pop();
cout<<q.front()<<"\n";
cout<<q.size()<<"\n";

\(3.2\) \(例题\)

luogu B3616 【模板】队列

\(3.3\) \(单调队列\)

类比与单调栈,我们也有单调队列,满足这个队列中,(比如求最大值)
权值是递减的,但是 id 是递增的,有单调性质。

关键性质同样是保留对于当前而言更优的一个信息。

为什么权值递减?因为我们要求目前最大值,为什么 id 递增?我们有
id 大于某个位置的限制。

\(4\) \(堆\)

\(4.1\) \(介绍\)

一种结构,维护一个序列,每次加入一个元素,询问当前序列中最小的
元素,然后删除最小元素。

具体维护,我们一般维护的称为二叉堆,即维护一个结构,支持上述处
理过程。

每个节点 \(i\) 储存一个权值,左儿子是 \(2 ∗ i\),右儿子是 \(2 ∗ i + 1\)。

\(4.2\) \(实现\)

\(4.3\) \(例题\)

luogu B3616

\(4.4\) \(对顶堆\)

一个序列,我们每次加入一个元素,或者进行询问。

维护一个初始指针 i=0,每次询问的时候将 i=i+1 然后询问第 i 小的值
是多少。

例题

\(5\) \(哈夫曼树\)

\(5.1\) \(例题引入\)

\(5.2\) \(详解\)

\(5.3\) \(例题\)

luogu p2168 荷马史诗

注意到,没有前缀包含关系完全对应了哈夫曼编码,而我们最优化次数
正好是哈夫曼树的最小的贡献!

所以我们建立扩展的 k 叉哈夫曼树即可得到答案。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int read()
{
	char c;
	int w=1;
	while((c=getchar())>'9'||c<'0')if(c=='-')w=-1;
	int ans=c-'0';
	while((c=getchar())>='0'&&c<='9')ans=(ans<<1)+(ans<<3)+c-'0';
	return ans*w;
}
priority_queue<pair<int,int> >q;
int a[5000005];
int n;
int k;
signed main(){
	n=read();
	k=read();
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
		q.push(make_pair(-a[i],-1));
	}
	while((n-1)%(k-1))n++,q.push(make_pair(0,-1));
	int anss=0;
	for(int i=1;i<=(n-1)/(k-1);i++)
	{
		int ans=0;
		int maxx=0;
		for(int j=1;j<=k;j++)
		{
			ans+=(-q.top().first);
			maxx=max(maxx,-q.top().second);
			q.pop();
		}
		anss+=ans;
		q.push(make_pair(-ans,-maxx-1));
	}
	cout<<anss<<endl<<-q.top().second-1<<endl;
	return 0;
}

\(二\) \(STL、差分、前缀和\)

\(1\) \(STL\)

STL 是 C++ 标准库的一部分,包含了很多数据结构和算法,我们可以
直接调用这些函数来解决问题。

比如说,我们可以直接调用 vector 来解决动态开数组的问题,调用 set
来解决集合(有序数组)的问题。

我们随着代码一起来理解一下这些 STL。

点击查看STL
#include<bits/stdc++.h>
#define ll long long
#define dd double
#define ull unsigned ll
#define LL __int128
#define siz(A) ((int)A.size())
using namespace std;
char gc(){static char buf[1<<16],*s,*t;if(s==t){t=(s=buf)+fread(buf,1,1<<16,stdin);if(s==t)return EOF;}return *s++;}
//#define getchar gc
ll read()

{
	char c;
	ll w=1;
	while((c=getchar())>'9'||c<'0')if(c=='-')w=-1;
	ll ans=c-'0';
	while((c=getchar())>='0'&&c<='9')ans=(ans<<1)+(ans<<3)+c-'0';
	return ans*w;
}
void pc(char c,int op)
{
	static char buf[1<<16],*s=buf,*t=(buf+(1<<16));
	(op||((*s++=c)&&(s==t)))&&(fwrite(buf,1,s-buf,stdout),s=buf);
}
void wt(int x)
{
	if(x>9)wt(x/10);
	pc('0'+x%10,0);
}
void wts(int x,char op)
{
	if(x<0)pc('-',0),x=-x;
	wt(x),pc(op,0);
}
namespace vec
{
	vector<int>v;
	void test()
	{
		
		vector<int>A(5);
		
		vector<int>B(5,3);
		
		vector<int>C={1,2,3};
		
		for(vector<int>::iterator it=A.begin();it!=A.end();it++)cout<<*it<<" ";
		puts("");
		
		for(auto it:B)cout<<it<<" ";
		puts("");
		
		for(int i=0;i<(int)C.size();i++)cout<<C[i]<<" ";
		puts("");
		
		
		int n=read();
		v.resize(100);
		
		cout<<(int)v.size()<<"\n";//unsigned
		
		cout<<(int)v.capacity()<<"\n";
		
		for(int i=1;i<=n;i++)
			v.push_back(i);
		
		cout<<(int)v.size()<<"\n";//unsigned
		
		cout<<(int)v.capacity()<<"\n";
		
		v.shrink_to_fit();
		
		cout<<(int)v.capacity()<<"\n";
		
		v.push_back(2);
		
		cout<<(int)v.size()<<"\n";
		
		cout<<(int)v.capacity()<<"\n";
		
		v.clear();
		
		cout<<(int)v.capacity()<<"\n";
		
		vector<int>().swap(v);
		
		cout<<(int)v.capacity()<<"\n";
	}
}
namespace basic
{
	basic_string<int>v;
	void test()
	{
		int n=read();
		v.resize(100);
		
		cout<<(int)v.size()<<"\n";//unsigned
		
		cout<<(int)v.capacity()<<"\n";
		
		for(int i=1;i<=n;i++)
			v.push_back(i);
		
		cout<<(int)v.size()<<"\n";//unsigned
		
		cout<<(int)v.capacity()<<"\n";
		
		v.shrink_to_fit();
		
		cout<<(int)v.capacity()<<"\n";
		
		v.push_back(2);
		
		cout<<(int)v.size()<<"\n";
		
		cout<<(int)v.capacity()<<"\n";
		
		v.clear();
		
		cout<<(int)v.capacity()<<"\n";
		
		basic_string<int>().swap(v);
		
		cout<<(int)v.capacity()<<"\n";
		
		basic_string<int>A={2,3,4};
		
		basic_string<int>B={2,3,4};
		
		for(auto it:A)cout<<it<<" ";
		puts("");
		
		A=A+B;
		
		for(auto it:A)cout<<it<<" ";
		puts("");
		
		//string 
		
		cout<<A.find({4,2})<<"\n"; 
		
		
	}
}

namespace se
{
	set<int>A;
	multiset<int>B;
	void test()
	{
		for(int i=1;i<=3;i++)
		{
			A.insert(i);//pair <bool,iterator>
			A.insert(i);
			
			B.insert(i);//指针 iterator  
			B.insert(i);
		}
		for(auto it:A)cout<<it<<" ";
		puts("");
		
		for(auto it:B)cout<<it<<" ";
		puts("");
		
		multiset<int>::iterator x=B.lower_bound(0);
		
		multiset<int>::iterator y=B.find(2);
		
		B.erase(x);
		
		for(auto it:B)cout<<it<<" ";
		puts("");
		
		B.erase(3);
		
		for(auto it:B)cout<<it<<" ";
		puts("");
		
		cout<<(int)B.size()<<"\n";
		
		cout<<(int)B.count(2)<<"\n";
		
		A.clear(),B.clear();
		//不能数组下标访问。 
		
	}
}


namespace ma
{
	map<int,int>A;
	unordered_map<int,int>B;
	void test()
	{
		for(int i=1;i<=3;i++)A[i]=i-1,B[i]=i-1;
		
		for(auto it:A)cout<<it.first<<" "<<it.second<<"\n";
		puts("");
		
//		for(auto it:B)cout<<it<<" ";
//		puts("");
		
		auto it=A.find(2);//key 
		
		cout<<A[4]<<"\n";
		
		A.clear(),B.clear();
		
	}
}

namespace bit
{
	bitset<10>bit,bb;
	void test()
	{
		bit[5]=1;
		cout<<bit<<"\n";
		
		bit.flip();
		bit<<=3;
		cout<<bit<<"\n";
		
		bb[1]=1;
		bb[4]=1;
		
		cout<<bb<<"\n";
		bit^=bb;
		cout<<bit<<"\n";
		
		int A=bit._Find_first();
		cout<<A<<"\n";
		
		cout<<bit._Find_next(A)<<"\n";
		
		
	}
}

int main(){
	vec::test();
	basic::test();
	se::test();
	ma::test();
	bit::test();
	
	
	pair<int,int>A;
	array<int,2>B;

//	stack
//	queue
//	priority_queue
//	sort();
//	merge();
//	nth_element();
//	next_permutation();
//	swap();
	
	
	vector<int>B=A;

	sort(A.begin(),A.end());
	A.resize(unique(A.begin(),A.end())-A.begin());
	for(auto it:B)cout<<it<<" ";
	puts("");
	for(int i=0;i<(int)B.size();i++)
	    B[i]=lower_bound(A.begin(),A.end(),B[i])-A.begin();
	
	for(auto it:B)cout<<it<<" ";
	puts("");
	
	
	pc('1',1);
	return 0;
}

\(2\) \(差分\)

\(2.1\) \(差分前缀和\)

是一个很简单的算法,我们可以用来解决一些区间的问题

\(2.2\) \(差分\)

若当前我们每次形如修改一个区间,使得区间加上一个值,最后我们需
要求出修改之后的数组我们应该怎么办呢?

我们可以用差分的方式,即对于每个区间 [l, r],我们让 al 加上 v,ar+1
减去 v。

\(3\) \(ST表\)

倍增在 OI 种是一个重要的思想,今天我们来介绍一下倍增思想的一个
应用:ST 表。

我们可以用 ST 表来解决一些区间的问题,最为经典的问题是,解决区
间极值的问题。

简要介绍一下 ST 表的原理:

给定一个长度为 N 的数列,和 M 次询问,求出每一次询问的区间内数
字的最大值。

标签:nx,int,void,元素,Day2,链表,暑假,2024QBXT,维护
From: https://www.cnblogs.com/TianJiajun-chaqjs/p/18305932

相关文章

  • 喜欢dp动态规划的第二天(暑假提升)
    不要失去信心,只要坚持不懈,就终会有成果。——钱学森dp动态规划题目详解--第二天前言1、最长定差子序列2、最长等差数列3、等差数列划分II-子序列4、回文子串5、总结前言由于上一期的动态规划我觉的太过于繁琐,所以这次简化一下操作,题目概念解析将不会再写,我直......
  • 2024信友队蓝润暑期集训提高1班②Day2
    知识总结转化、构造、模拟。转化:将算法转化为其他形式。构造:通过算法构造一个模型。模拟:通过算法模拟一个过程。随堂练习T1排行榜题目描述https://www.luogu.com.cn/problem/P1159思路解析显然这题可以直接贪心。把一首一首歌往排行榜上放。对于SAME的歌,直接放在原......
  • android学习day2
    activity是应用程序的组件xml:描绘应用界面java:编写程序逻辑1.完整页面的创建过程:在layout目录下创建xml文件创建xml文件对应的java代码在AndroidManifest中注册页面配置 <?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="http://schemas.android......
  • NSSCTF中24网安培训day2中web题目
    [SWPUCTF2021新生赛]ez_unserialize这道题目考察php反序列化的知识点打开题目,发现没有提示,我们试着用御剑扫描目录文件,发现存在robots.txt的文件接着访问这个文件,发现是一段php反序列化代码,我们需要进行序列化的转换简单的构造exp代码如下,在末尾那里<?phperror_re......
  • 代码随想录day25 复原IP地址 | 子集 | 子集II
    复原IP地址复原IP地址解题思路首先要判断什么是正确的IP地址:段位以0为开头的数字不合法段位里有非正整数字符不合法段位如果大于255了不合法接着就是要通过一个变量来存储加'.'的次数,然后将字符串分成四分,每段都需要检查是否符合条件。知识点回溯(分割),字符串心得这是......
  • Day2小结.(7.14)
    今天又是全天打比赛。https://www.cnblogs.com/didiao233/p/18301992T1(100)签到题,10分钟内切出来了,还算可以 https://www.cnblogs.com/didiao233/p/18302004T2(10)赛场想到贪心,不过没有考虑最关键的量,而是两个量一起贪心了,结果是显然的,爆炸了。所以,以后贪心得关注最重要的量......
  • 暑假第一周周报
    主要学习了二分算法:写了一些经典的二分算法;还写了一些和其他算法结合的二分:递归分治,题目:给一个数组{a},定义h(a,b)为在十进制下a+b与a的位数差,求和所有的h(ai,aj),0<i<j<n;不能暴力n方,用分治的思想,分解成最小的子问题求两个数的位数差,再层层往上归并,将后半段排序后,枚......
  • 2024 暑假友谊赛 1 (7.13)zhaosang
    A-Ahttps://vjudge.net/contest/638765#problem/A一开始贪心做不出来,后面发现是dp找到转移方程即可,01dp问题代码如下#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;llv[10000010];lln;llans;llprefix[10000010];intmain(){ intN; cin>>......
  • 2024 暑假友谊赛-热身2 (7.12)zhaosang
    E-Ehttps://vjudge.net/problem/AtCoder-diverta2019_b给你a,b,c,n就是问你有多少(ia+jb+k*c)等于n的答案i,j,k任意几个都可以为零两种思想,数据量比较小,那么可以三重循环+减枝,或者枚举两个变量算出第三个代码如下:第一种三重循环#include<bits/stdc++.h>usingnamespa......
  • 暑假第一周周报
    这周除了个人赛外,还进行了线段树、数状数组的练习。刚开始训练的时候,对线段数和数状数组是缺乏理解,感觉非常非常难,但随着做了越来越多的题。感觉现在是掌握了其中一部分。刚开始学线段树,其中的懒标记感觉不是太会,于是就网上找了一些资料,把那个懒标记的相关知识点给学了一下。个人......