NOI 大纲计划

将会对照 NOI 大纲的 提高级 内容进行刷题,每个知识点 \(2\)\(5\) 题左右

您可以在 这里 看到此计划的全部源代码

成员函数与运算符重载

struct student
{
    int id, score;

    student(int _id = 0, int _score = 0)
    {
        id = _id;
        score = _score;
    }
};

vector <student> v;

int main()
{
      v.push_back(student(1,2));
}
  • 运算符重载
struct student
{
    int id, score;

    friend bool operator < (student a, student b)
    {
        if(a.score != b.score) return a.score<b.score;
        return a.id<b.id;
    }
}a[10];

STL 模板

  • set
set<int> s;//定义 
s.insert(1);//插入元素 1
s.erase(1);//删除元素 1
s.size();//元素个数
s.count(2);// 2 的个数
s.empty();
s.clear();

遍历使用 auto

for(auto it:s)
  cout<<it<<' ';

其中 unordered_set 为无序 set .

  • list

待更新

  • deque

待更新

  • priority_queue
//升序队列
priority_queue <int,vector<int>,greater<int> > q;
//降序队列
priority_queue <int,vector<int>,less<int> >q;

q.empty();
q.top();
q.push();
  • multiset

set 不可以插入重复数据,而 multiset 可以

  • map

当数组用.

  • multimap

map 不允许键值对重复,但 multimap 允许。

  • pair

不介绍.
因为我懒

  • tuple

相当于结构体.

数据结构

此部分 不全部介绍 .

  • ST 表

ST 表是用于解决 可重复贡献问题 的数据结构。

除 RMQ 以外,还有其它的“可重复贡献问题”。例如“区间按位和”、“区间按位或”、“区间 GCD”,ST 表都能高效地解决。其实只要线段树/树状数组写得熟,根本不用它

ST 表基于 倍增 思想,可以做到 \(O(n \log n)\) 预处理, \(O(1)\) 回答每个询问。但是不支持修改操作。

ST / RMQ 模板题

const int N = 100000 + 7;
int n,m;
int maxx[N][21];
int calc(int l,int r)
{
	int mid = log2(r-l+1);
	return max(maxx[l][mid],maxx[r-(1<<(mid))+1][mid]);

}
int main()
{
	read(n);read(m);
	for(int i=1;i<=n;i++)
		read(maxx[i][0]);
	int k = log(n)/log(2) + 1;
	for(int j=1;j<=k;j++)
		for(int i=1;i+(1<<j)-1<=n;i++)
			maxx[i][j]=max(maxx[i][j-1],maxx[i+(1<<(j-1))][j-1]);
	while(m--)
	{
		int x,y;
		read(x);read(y);
		int ans = calc(x,y);
		printf("%d\n",ans);
	}
	return 0;
}

「SCOI2007」降雨量

没做。

[USACO07JAN] Balanced Lineup G

View my code

  • 线段树

线段树模板1

View my code

  • 树状数组

主要解决 单点修改,区间查询区间修改,单点查询 的问题(其实其他主要是因为我不会)

// 单点修改,区间查询 
#include<bits/stdc++.h>

using namespace std;
int lowbit(int x)
{
	return x & -x;
}
const int Maxn = 5e5 + 7;
int n,m;
int tree[Maxn],a[Maxn],c[Maxn];
void updata(int x,int k)
{
	while(x<=n)
	{
		c[x]=c[x] + k;
		x = x + lowbit(x);
	}
}
int getsum(int x)
{
	int ans = 0;
	while(x>=1)
	{
		ans+=c[x];
		x=x-lowbit(x);
	}
	return ans;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		updata(i,a[i]);
	}
	for(int i=1;i<=m;i++)
	{
		int op,x,y;
		cin>>op>>x>>y;
		if(op==1)	updata(x,y);
		else
			cout<<getsum(y)-getsum(x-1)<<endl;
	}
	return 0;
}

// 区间修改,单点查询 
#include<bits/stdc++.h>

using namespace std;
int lowbit(int x)
{
	return x & -x;
}
const int Maxn = 5e5 + 7;
int n,m;
int a[Maxn],c[Maxn];
void updata(int x,int k)
{
	while(x<=n)
	{
		c[x]=c[x] + k;
		x = x + lowbit(x);
	}
}
int getsum(int x)
{
	int ans = 0;
	while(x>=1)
	{
		ans+=c[x];
		x=x-lowbit(x);
	}
	return ans;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		updata(i,a[i]-a[i-1]);
	}
	for(int i=1;i<=m;i++)
	{
		int op,x,y,k;
		cin>>op;
		if(op==1)
		{
			cin>>x>>y>>k;
			updata(x,k);
			updata(y+1,-k);
		}
		else
		{
			cin>>x;
			cout<<getsum(x)<<endl;
		}
			
	}
	return 0;
}

其实对于 区间修改,单点查询 ,还是有点东西的。

首先考虑差分数组:

比如 \(A= \{a_1,a_2,a_3,a_4,a_5 \}\) .

则有 \(B= \{ a_1,a_2-a_1,a_3-a_2,a_4-a_3,a_5-a_4 \}\) .

那么对于区间加,只需要头加,尾减.查询时再做一个前缀和,就是当前的值。

可能线段树的区别就是难以解决 区间修改,区间查询 问题吧(当然,也可能是我不会呢)

数学

高中数学

你看我会嘛 QAQ

初等数论

  • 同余式

若两数 \(a,b\) 除以 \(c\) 的余数相等,则称 \(a,b\)\(c\) 同余,记做 $ a \equiv b (mod c)$ .

  • 欧几里得算法

求出 \((a,b)\) ,求出 \(a,b\) 两个数的最大公因数。

int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
// 坑点:这里不能写成 b % a
  • 扩展欧几里得算法

void exgcd(int a,int b,int &x,int &y)
{
	if(b==0)	{x=1;y=0;return;}
	exgcd(b,a%b,y,x);
	y-=a/b*x;
}

二元一次不定方程 (exgcd)

因为细节比较多,我不一定会(捂脸

  • 裴蜀定理

\(\forall a,b,\exists x,y,s.t.ax+by=(a,b)\)

组合数学

待更。

线性代数

其实主要是 矩阵

对于 矩阵转置运算 ,这里举例说明:

\[\begin{pmatrix}1&2&3\\4&5&8\end{pmatrix} \Rightarrow \begin{pmatrix}1&4\\2&5\\3&8\end{pmatrix} \]

  • 矩阵加速递推

View my code

posted @ 2022-08-20 07:28  xlqs23  阅读(82)  评论(0编辑  收藏  举报