Noip2018 考前准备

目录

  • 基础算法
    • 二分
    • 模拟(未补)
    • 高精(未学习)
    • 搜索(未补)
    • 排序
  • 图论
    • 树的直径
    • 树的重心
    • 最短路算法
      • Spfa
      • Dijkstra
      • Floyd
    • 最小生成树
      • kruskal
  • 数论
    • 线性筛
      • 线性筛素数
      • 线性筛phi
      • 线性筛莫比乌斯函数
    • gcd(最大公因数)
    • lcm(最小公倍数)
    • 快速幂
    • 扩展欧几里得算法
    • 逆元
    • 矩阵快速幂
  • 数据结构
    • ST表
    • 并查集

未完成先看吧.大概9.1号完成.
然而现在都8102年了...

基础算法

二分

求最小值最大.
跳石头

#include 
#include 
using namespace std;
const int maxN = 50000 + 7;

int a[maxN],n,m;
int L;

inline int read() {
    register int x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
    return x * f;
}

bool calc(int k) {
    int num = 0,path = 0;
    for(int i = 1;i <= n;++ i) {
        if(a[i] - a[path] < k) { 
            num ++;
        }else path = i;
    }
    return num <= m;
}

int main() {
    L = read();n = read();m = read();
    for(int i = 1;i <= n;++ i) a[i] = read();
    n ++;
    a[n] = L;
    int l = 0,r = L,ans;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(calc(mid)) {
            ans = mid;
            l = mid + 1;
        }
        else r = mid - 1;
    }
    printf("%d",ans);
    return 0;
}

模拟(未补)

高精(未学习)

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;



struct bignum
{
    int n;
    int a[500];
    bignum()
    {
        n = 0;
        memset(a, 0, sizeof(a));
    }
        
    bignum(string s)
    {
        n = s.size();
        memset(a, 0, sizeof(a));
        for (int i = 0; i < n; i++)
            a[i] = s[n - 1 -i] -'0';
    }
    bignum(int s)
    {
        memset(a, 0, sizeof(a));
        n = 0;
        while (s > 0)
        {
            a[n] = s % 10;
            s /= 10;
            n++;
        }
    }
    void work()
    {
        for (int i = 0; i < n; i++)
        {
            if (a[i] < 0)
            {
                int tmp = (-a[i] - 1) / 10 + 1;
                a[i] += 10 * tmp;
                a[i + 1] -= tmp;
            }
            if (a[i] >= 10)
            {
                int tmp = a[i] / 10;
                a[i] -= 10* tmp;
                a[i + 1] += tmp;
                if (i == n - 1 && a[i + 1] > 0) n++;
            }
        }
        while (n > 0 && a[n - 1] == 0) n--;
    }
    void print()
    {
        for (int i = n - 1; i >= 0; i--)
            cout << a[i];
        cout << endl;
    }
};

bignum operator + (const bignum &a, const bignum &b)
{
    bignum c;
    c.n = max(a.n, b.n);
    for (int i = 0; i < c.n; i++)
        c.a[i] = a.a[i] + b.a[i];
    c.work();
    return c;
}


bignum operator - (const bignum &a, const bignum &b)
{
    bignum c;
    c.n = max(a.n, b.n);
    for (int i = 0; i < c.n; i++)
        c.a[i] = a.a[i] - b.a[i];
    c.work();
    return c;
}


bignum operator * (const bignum &a, const bignum &b)
{
    bignum c;
    c.n = a.n + b.n - 1;
    for (int i = 0; i < a.n; i++)
        for (int j = 0; j < b.n; j++)
            c.a[i + j] += a.a[i] * b.a[j];
    c.work();
    return c;
}


int main()
{
    string s;
    cin >> s;
    int x;
    cin >> x;
    bignum a(s);
    bignum b(x);
    (a + b).print();
    (a - b).print();
    (a * b).print();
    return 0;
}

搜索(未补)

排序

merge_sort(归并排序)

#include 
#include 
const int maxN = 100000 + 7;

int z[maxN],a[maxN];

inline int read() {
    int x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
    return x * f;
}

void merge(int l,int r) {
    if(l == r) return;
    int mid = l + r >> 1;
    merge(l,mid);
    merge(mid + 1,r);
    int z1 = l,z2 = mid + 1;
    for(int i = l;i <= r;++ i) {
        if(z1 <= mid) 
            if(z2 <= r) 
                if(a[z1] >= a[z2]) z[i] = a[z2 ++];
                else z[i] = a[z1 ++];
            else z[i] = a[z1 ++];
        else z[i] = a[z2 ++];
    }
    for(int i = l;i <= r;++ i) 
        a[i] = z[i];
}
 
int main() {
    int n = read();
    for(int i = 1;i <= n;++ i) 
        a[i] = read();
    merge(1,n);
    for(int i = 1;i <= n;++ i) 
        printf("%d ",a[i]);
    return 0;
}

图论

树的直径

POJ2631

#include 
#include 
#include 
#include 
const int maxN = 10000 + 7;
using namespace std;

int ans,id,n = 1;
int Rode[maxN];

struct Node{
    int v,w;
};

vectorQ[maxN];

void dfs1(int now,int fa) {
    for(int i = 0;i < Q[now].size();++ i) {
        int v = Q[now][i].v,w = Q[now][i].w;
        if(v == fa) continue;
        Rode[v] = Rode[now] + w;
        dfs1(v,now);
    }
    return;
}

int max(int a,int b) {
    return a > b ? a : b ;
}

int main() {
    #ifdef WIN32
    freopen("a.txt","r",stdin);
    #endif
    int u,v,w;
    while(scanf("%d%d%d",&u,&v,&w) == 3) {
        Q[u].push_back((Node) {v,w});
        Q[v].push_back((Node) {u,w});
        n ++;
    }
    dfs1(1,-1);
    for(int i = 1;i <= n;++ i) {        
        if(ans < Rode[i]) {
            ans = Rode[i];
            id = i;
        }
    }
    memset(Rode,0,sizeof(Rode)); 
    dfs1(id,-1);
    ans = 0;
    for(int i = 1;i <= n;++ i)
        ans = max(ans,Rode[i]);
    printf("%d",ans);
    return 0;
}

树的重心

POJ1655

#include 
#include 
#include  
const int maxN = 20000 + 7;
using namespace std;
 
vector g[maxN];
int n;
int ans,id;

int max(int a,int b) {return a > b ? a : b;}
int min(int a,int b) {return a > b ? b : a;}

int dfs(int now,int fa) {
    int son = 1,maxson = 0,kkk;
    for(int i = 0;i < g[now].size();++ i) {
        int v = g[now][i];
        if(v == fa) continue;
        int Q = dfs(v,now);
        son += Q;
        maxson = max(maxson,Q);
    }
    kkk = max(maxson,n - son);
    if(kkk < ans) {
        ans = kkk;
        id = now;
    }
    return son;
}

int main() {
    int T;
    scanf("%d",&T);
    while(T --) {
        scanf("%d",&n);
        for(int i = 1;i <= n;++ i) 
            g[i].clear(); 
        for(int i = 1,u,v;i < n;++ i) {
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        ans = 0x7fffffff;
        dfs(1,-1);
        printf("%d %d\n",id,ans);
    } 
    return 0;
}

最短路算法

题目单源最短路径(弱化版)

Spfa

#include 
#include 
#include 
#include 
const int maxN = 100000 + 7;
const int maxM = 200000 + 7;
const int inf = 2147483647;
using namespace std;

int dis[maxN];
bool vis[maxN];
int max(int a,int b) {return a > b ? a : b;}
int min(int a,int b) {return a > b ? b : a;}

struct Node{
    int v,w,nex;
}Map[maxM];

int head[maxN],num;

void add_Node(int u,int v,int w) {
    Map[++ num].v = v;
    Map[num].w = w;
    Map[num].nex = head[u];
    head[u] = num;
    return;
}

void spfa(int now) {
    queueq;
    q.push(now);
    vis[now] = true;
    dis[now] = 0;
    while(!q.empty()) {
        int u = q.front();q.pop();
        vis[u] = 0; 
        for(int i = head[u];i != -1;i = Map[i].nex) {
            int v = Map[i].v;
            if(dis[v] > dis[u] + Map[i].w) {
                dis[v] = dis[u] + Map[i].w;
                if( !vis[v] ) {
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    return ;
}

int main() {
    memset(dis,0x3f,sizeof(dis));
    memset(head,-1,sizeof(head));
    int n,m,s;
    scanf("%d%d%d",&n,&m,&s);
    for(int i = 1,u,v,w;i <= m;++ i) {
        scanf("%d%d%d",&u,&v,&w);
        add_Node(u,v,w);
    }
    spfa(s);
    for(int i = 1;i <= n;++ i) 
        printf("%d ",dis[i] == 0x3f3f3f3f ? inf : dis[i]);
    return 0;
}

Dijkstra

#include 
#include 
#include 
using namespace std;
const int inf = 0x7fffffff;
const int maxN = 100000 + 7;
const int maxM = 200000 + 7;

struct Node{
    int x,y;
    inline bool operator < (const Node &a) const {
        return y > a.y;
    }
}; 
priority_queue q;
struct qode{
    int v,nex,w;
}Map[maxM];

int s,dis[maxN],n,m,num,head[maxN];

void add_Node(int u,int v,int w) {
    Map[++ num].v = v;
    Map[num].w = w;
    Map[num].nex = head[u];
    head[u] = num; 
}

void dij() {
    for(int i = 1;i <= n;++ i) dis[i] = inf;
    q.push((Node){s,0});
    dis[s] = 0;
    while(!q.empty()) {
        Node x = q.top();q.pop();
        if(x.y != dis[x.x]) continue;
        for(int i = head[x.x];i;i = Map[i].nex) {
            int v = Map[i].v;
            if(dis[v] > dis[x.x] + Map[i].w) {
                dis[v] = dis[x.x] + Map[i].w;
                q.push((Node){v,dis[v]});
            }
        }
    } 
    for(int i = 1;i <= n;++  i) {
        printf("%d ",dis[i]);
    }
}

int main() {
    scanf("%d%d%d",&n,&m,&s);
    for(int i = 1,u,v,w;i <= m;++ i) {
        scanf("%d%d%d",&u,&v,&w);
        add_Node(u,v,w);
    }   
    dij();
    return 0;
}

Floyd

#include 
#include 
#include 
#include 
using namespace std;
int a[101][101];
int main()  {
    int n,m,s;
    scanf("%d%d%d",&n,&m,&s);
    memset(a,0x3f,sizeof(a));
    for(int i = 1,u,v,w;i <= m;++ i) {
        scanf("%d%d%d",&u,&v,&w);
        a[u][v]=min(a[u][v],w);
    }
    for(int k = 1;k <= n;++ k) 
        for(int i = 1;i <= n;++ i)
            for(int j = 1;j <= n;++ j) 
                a[i][j] = min(a[i][j],a[i][k] + a[k][j]);
    a[s][s] = 0;
    for(int i = 1;i <= n;++ i) {
        printf("%d ",a[s][i] == 0x3f3f3f3f ? 2147483647 : a[s][i]);
    }
}

最小生成树

kruskal

#include 
#include 
#include 
using namespace std;
const int maxN = 5000 + 7;
const int maxM = 200000 + 7;

inline int read() {
    int x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
    return x * f;
}
struct Node {
    int u,v,w;
}Q[maxM];
int fa[maxN];

int find(int x) {
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}

void un(int a,int b) {
    int faa = find(a),fab = find(b);
    fa[faa] = fab;
    return;
}

bool cmp(Node a,Node b) {
    return a.w < b.w;
}

int num = 0;
void add_Node(int u,int v,int w) {
    Q[++ num].u = u;
    Q[num].v = v;
    Q[num].w = w;
}

int main() {
    int n,m;
    n = read();m = read();
    for(int i = 1;i <= n;++ i) fa[i] = i;
    for(int i = 1,u,v,w;i <= m;++ i) {
        u = read();v = read();w = read();
        add_Node(u,v,w);
    }
    sort(Q + 1,Q + m + 1,cmp);
    int sum = 0,k = 0;
    for(int i = 1;i <= m;++ i) {
        int fau = find(Q[i].u),fav = find( Q[i].v);
        if(fau != fav) {
            k ++ ;
            sum += Q[i].w;
            un(fau,fav);
            if(k == n - 1) break;
        }
    }
    if(k == n - 1) printf("%d",sum);
    else printf("orz");
}

数论

线性筛

线性筛素数

void init1(int n) {
    vis[1] = 1;
    for(int i = 2;i <= n;++ i) {
        if(!vis[i]) prime[++ num] = i;
        for(int j = 1;prime[j] * i <= n;++ j) {
            vis[i * prime[j]] = true;
            if(i % prime[j] == 0) break;
        }
    }
} 

线性筛phi

int phi[maxN];
void init2(int n) {
    vis[1] = 1;
    phi[1] = 1;
    for(int i = 2;i <= n;++ i) {
        if( !vis[i] ) {
            prime[++ num] = i;
            phi[i] = i - 1;
        }
        for(int j = 1;j <= num && prime[j] * i <= n;++ j) {
            vis[i * prime[j]] = true;
            if(i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            phi[i * prime[j]] =  phi[i] *( prime[j] - 1);
        }
    }   
}

线性筛莫比乌斯函数

int mu[maxN];
void init3(int n) {
    vis[1] = 1;
    mu[1] = 1;
    for(int i = 2;i <= n;++ i) {
        if(!vis[i]) {
            prime[++ num] = i;
            mu[i] = -1;
        }
        for(int j = 1;j <= num && prime[j] * i <= n;++ j) {
            vis[i * prime[j]] = true;
            if(i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }
    return;
} 

gcd(最大公因数)

int gcd(int a,int b) {
    while(b ^= a ^= b ^= a %= b);
    return a;
}

lcm(最小公倍数)

int lcm(int a,int b) {
    return a / gcd(a,b) * b;
}

快速幂

int fast_pow(int a,int b,int k) {
    int ans = 1;
    for(int now = a;b;b >>= 1,now = now * now) {
        now %= k;
        if(b & 1) ans *= now;
        ans %= k;
    }
    return ans % k;
}

扩展欧几里得算法

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

逆元

nt inv(int n,int p) {
    for(int i = 1,x,y;i <= n;++ i) {
        exgcd(i,p,x,y);
        printf("%d\n",(x % p + p) % p);
    }
} //a * x ≡ q (mod p)

矩阵快速幂


ll n,m,k;
struct Marix{
    ll s[107][107];
    void clear() {
        memset(s,0,sizeof(s));
        return;
    }
}ans,now,a;

Marix work(Marix a,Marix b) {
    Marix c;
    c.clear();
    for(ll i = 1;i <= n;++ i) 
        for(ll j = 1;j <= n;++ j) 
            for(ll k = 1;k <= n;++ k) 
                c.s[i][j] = ( c.s[i][j]  % mod+ ( a.s[i][k] * b.s[k][j] ) % mod ) % mod;
    return c;
}

void fast_pow() {
    ans.clear();
    for(ll i = 1;i <= n;++ i) {
        ans.s[i][i] = 1;
    }
    for(now = a;k;k >>= 1,now = work(now,now)) {
        if(k & 1) ans = work(ans,now);
    }
    for(ll i = 1;i <= n;++ i) {
        for(ll j = 1;j <= n;++ j) {
            printf("%lld ",ans.s[i][j]);
        }
        puts("");
    }
}
void Marix_fast_power() {
    scanf("%lld%lld",&n,&k);
    for(int i = 1;i <= n;++ i) {
        for(int j = 1;j <= n;++ j) {
            scanf("%lld",&a.s[i][j]);
        }
    }
    fast_pow();
    return ;
}

数据结构

ST表

#include 
#include 
#define max(a,b) a > b ? a : b
#define min(a,b) a > b ? b : a
const int maxN = 1e5 + 7; 
using namespace std;
int f[maxN][21];
int a[maxN];
int bin[maxN];
int n,m;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}

void build_st() {
    for(int i = 1;(1 << i) <= n;++ i) 
        bin[(1 << i)] = i;
    for(int i = 3;i <= n;++ i)
        if(!bin[i]) bin[i] = bin[i - 1];
    for(int i = 1;i <= n;++ i) 
        f[i][0] = a[i];
    for(int j = 1;(1 << j) <= n;++ j) {
        for(int i = 1;i + (1 << j) - 1 <= n;++ i) {
            f[i][j] = max(f[i + (1 << (j - 1))][j - 1],f[i][j - 1]);
        } 
    }
}

int query(int l,int r) {
    int x = bin[r - l + 1];
    return max(f[l][x],f[r - (1 << x) + 1][x]); 
}
int main() {
    n = read();m = read();
    for(int i = 1;i <= n;++ i) 
        a[i] = read();
    build_st();
    int l,r;
    while(m --) {
        l = read();r = read();
        printf("%d\n",query(l,r));
    }   
    return 0;
}

并查集

#include 
#include 
using namespace std;
const int maxN = 10000 + 7;

int fa[maxN];

inline int read() {
    int x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
    return x * f;
}

int find(int x) {
    return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);
}

void unit(int u,int v) {
    int fau = find(u),fav = find(v);
    fa[fau] = fav;
    return;
}

int main() {
    int n,m;
    n = read();m = read();
    for(int i = 1;i <= 10000;++ i) 
        fa[i] = i;
    int opt,u,v;
    while(m -- ) {
        opt = read();u = read();v = read();
        if(opt & 1) unit(u,v);
        else {
            int fau = find(u),fav = find(v);
            if(fau == fav) printf("Y\n");
            else printf("N\n");
        }
    }
}

转载于:https://www.cnblogs.com/tpgzy/p/9451825.html

你可能感兴趣的:(数据结构与算法)