冲刺NOIp2016算法模板(C++)

冲刺NOIp2016算法模板

程序大部分没经过编译和测评,欢迎在评论区指出本文中的错误
另:点开右下角像WIFI一样的标志进入RSS模式即可避免索引目录鬼畜的问题(可能需要向下翻一会才能找到本篇文章)

NOIp竞赛中还可能会用到的模板:Tarjan等,请大家注意一下

记得考前一定要练好DFS和记忆化DFS!!骗分必用!

C++


Catalogue:


数据结构

int strack[maxn];
int head;
bool b[maxn];

void push(int x)
{
    strack[++head]=x;
    b[x]=true;
};

int pop()
{
    int ret;
    ret=strack[head--];
    b[ret]=false;
    return ret;
};

bool empty()
{
    return head>0;
}

队列

int queue[2*maxn];
int tail,head;
bool b[maxn];

void push(int x)
{
    queue[++tail]=x;
    bool[x]=true;
};

int pop()
{
    int ret;
    ret=queue[++head];
    b[ret]=false;
    return ret;
};

bool empty()
{
    return head>=tail;
};  

当然有的时候你手写的数据结构需要比较大的空间,这样队列就会造成很多损失,所以相应的就有两种解决方法:一:STL;二:循环队列,只需改两个地方(代码如下);

head=(head+1)%n+1;//把head++改
tail=(tail+1)%n+1;//把tail++改

树状数组

int lowbit(int x)
{
    return x&-x;
};

int getsum(int n) //求1~n见的和
{
    int ret=0;
    while(n)
    {
        ret+=c[n];
        n-=lowbit(n);
    };
    return ret;
};

void add(int n,int x) //给a[n]加上x
{
    a[n]+=x;
    while(n<=maxn)
    {
        c[n]+=x;
        n+=lowbit(n);

应用模型:

  • 树状数组求逆序对:
void update(int n)
{
    while(n<=maxn)
    {
        c[n]+=1;
        n+=lowbit(n);
    };
};

for(int i = 1; i <= n; ++i)  //主程序里面加上这个
{  
    update(reflect[i]);  
    ans += i - getsum(reflect[i]);//reflect是离散化后的数组
} 

单调队列

以下单调队列的标程就用的音乐会的等待的。

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=500005;
int n,l,ans;
long long q[maxn],bef[maxn];
int main()
{
    cin>>n;
    q[0]=-1;
    long long a;
    for(int i=1;i<=n;i++)
    {
        cin>>a;
        while(l>0&&a>q[l])
        {
            l--;
            ans++;
        };
        if(l!=0)
        {
            if(a!=q[l])ans++;else
            {
                ans+=bef[l];
                if(bef[l]<l)ans++;
            };
        };
        l++;q[l]=a;
        if(q[l-1]==a)bef[l]=bef[l-1]+1;else bef[l]=1;   
    };
    cout<<ans;
    return 0;
}

STL

关于每个STL我只会写一下是什么,怎么用(举例子的形式),不会说的太细

Vector

不定长度数组

#include <vector>
vector<int> first;  //第一种定义方法

int myints[]={
  16,2,77,29};
vector<int> second(myints,myints+4);//第二种定义方法

sort(second.begin(),second.end());//对vector排序

a=second[i];//可以这么使用

//以下是对vector的操作

Vector<int> opt;

opt.begin();    //返回起始地址
opt.end();  //返回结束地址
opt.size(); //返回大小
opt.empty();    //返回是否vector为空
opt.back(); //返回最后一个push进的数
opt.pop_back(); //把最后一个数弹出(不返回)
opt.push_back(int x);//把x从后面push进去

opt.erase(opt.begin(),opt.begin()+3);//删掉前三个元素
opt.erase(opt.begin()+5);//删掉第6个元素

Queue

队列,操作与Stack一样。

Priority_queue

相当于堆

#include <queue>

priority_queue<int> Bigheap;//定义一个大根堆
priority_queue<int,vector<int>,greater<int> > Smallheap;//定义一个小根对(注意两个尖括号间有空格)

//以下是操作

priority_queue<int> opt;
opt.top();//返回堆顶元素的值(不弹出)
opt.pop();//弹出堆顶元素(无返回值)
opt.push(x);

Stack

stack<int> opt;
opt.front();//返回
opt.size();
opt.empty();
opt.push();
opt.pop();//弹出

Deque

双向队,操作与Stack一样

Bitset

压位神器,只普及一下,不会用。

Set

set<int> first;
int myints[]= {
  10,20,30,40,50};
set<int> second (myints,myints+5);
set<int> third (second);
set<int> fourth (second.begin(), second.end());
third.rbegin(); third.rend();//rend相当于begin,rbegin相当于end
third.size();//返回大小
third.insert(60);
third.erase(it);
third.erase(50);//删除元素'50'
third.find(10);//找元素'10'
third.lower_bound(30); third.upper_bound(30);//'30'出现的第一个位置/最后一个位置
third.clear();//清除

Multiset

与Set用法一样,只是允许重复元素。

Map

map<char,int> first;
first[‘a’] = 10;
first.insert(make_pair(‘b’,20));
it++; ++it; it--; --it;
first.erase(1);//删除元素
firstt.count(1);//看有没有关系

Algorithm里其他好用的函数

Next_permutation
int a[]={
  1,2,3,4};

next_permutation(a,a+3);//下一个全排列

//现在a数组变成了:1 2 4 3
Lower_bound与Upper_bound
lower_bound(first,last,val);//有返回值
upper_bound(first,last,val);
Merge
merge (first,first+5,second,second+5,v.begin(),compare);
sort
bool compare(int a,int b)
{
    return a<b;
};//compare函数的例子

sort(起始地址,结束地址,compare函数);
Reverse
Reverse(myvector.begin(),myvector.end());
Unique
bool myfunction (int i, int j)
{
  return (i==j);
}

unique(起始地址,结束地址,去重条件函数);//按照函数里面编写的规则去重,当然也可以没有第三个参数
Random_shuffle

留一个概念,不会用,生成数据的时候用。

数论

快速幂

普通快速幂
#define ull unsigned long long
ull qpow(ull x,ull y,ull p) // x^y mod p
{
    ull ret=1;
    while(y)
    {
        if(y&1)ret = ret * x % p;
        x=x*x%p;
        y>>=1;
    };
    return ret;
}
矩阵快速幂
matrix operator *(matrix m1,matrix m2)//重载运算符
{
    assert(m1.m==m2.n);
    matrix res;
    res.n=m1.n; res.m=m2.m;
    for(int i=0;i<m1.n;i++)
        for(int j=0;j<m2.m;j++)
            for(int k=0;k<m1.m;k++)
                res.mat[i][j]+=m1.mat[i][k]*m2.mat[k][j];
    return res;
}

matrix matrix_pow(matrix x,int y)
{
    matrix res;
    res.n=res.m=2;
    res.mat[0][0]=res.mat[1][1]=1;
    while(y)
    {
        if(y&1)res=res*x;
        x=x*X;
        y>>=1;
    }
    return res;
}

筛法求素数

欧拉筛法
int tot=0;
void euler(int n)
{
    memset(check,0,sizeof(check));
    for(int i=1;i<=n;i++)
    {
        if(!check[i])prime[++tot]=i;
        for(int k=1;k<=tot;k++)
        {
            if(i*prime[k]>n)break;
            check[i*prime[k]]=1;
            if(i%prime[k]==0)break;
        };
    };
};

应用举例:

验证素数

普通方法
bool flag=true;
for(int i=1;i<=trunc(sqrt(prime));i++)
    if(prime%i==0)flag=false;//置不是素数标志
Miller-Rabin

时间复杂度: O(klog2n) k是次数(见下文)
难度:★★★

这里只说明一下原理,关于代码,自行百度吧。

  • 根据费马小定理,随机选一个数 a(1,p) ,若
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值