【テンプレート】洛谷

前言

  【2017-11-10】

    哇!突然发现搜索‘模板’能搜到一坨。。。开始了默默刷模板的漫长之路。。。就让我最后在挣扎一下下吧!!!

  【2017-11-18】

    考完试了,忽然就发现,原来,不会的东西现学不可能会使用上的。。除了我瞎写的dijkstra,没用上这些模板,noip甚至连暴力都没写好。心态爆炸。

    嗯,还是在AFO后好好学文化课吧!

板砸们

1. P1177 【模板】快速排序

直通

好吧,不可相信这也是个模板。。

虽然说的那么。。那什么。。可是,真的不想自己弄唉(STL大法好)

代码酱=u=

①sort大法好!

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

int n;
long long a[100010];

int main() {
    scanf("%d",&n);
    for(int i=0; i<n; i++) scanf("%lld",&a[i]);
    sort(a,a+n);
    for(int i=0; i<n; i++) printf("%lld ",a[i]);
    return 0;
}
View Code

②真板子

——快速排序

#include <iostream>
#include <cstdio>
#include <algorithm>
#define mid ((l+r)>>1)
#define LL long long
using namespace std;

int n;
LL a[100010];

void Mysort(int l,int r) {
    int i=l,j=r,m=a[mid];
    while(i<=j) {
        while(a[i]<m) i++;
        while(a[j]>m) j--;
        if(i<=j) {
            LL tmp=a[i];
            a[i]=a[j],a[j]=tmp;
            i++,j--;
        }
    }
    if(l<j) Mysort(l,j);
    if(i<r) Mysort(i,r);
}

int main() {
    scanf("%d",&n);
    for(int i=0; i<n; i++) scanf("%lld",&a[i]);
    Mysort(0,n-1);
    for(int i=0; i<n; i++) printf("%lld ",a[i]);
    return 0;
}
View Code

——归并排序

#include <iostream>
#include <cstdio>
#define LL long long
using namespace std;

const int M = 100010;
int n;
LL a[M],b[M];

void gsort(int l,int r) {
    if(l==r) return;
    int mid=l+r>>1;
    gsort(l,mid),gsort(mid+1,r);
    int i=l,j=mid+1,k=l;
    while(i<=mid && j<=r) {
        if(a[i]<=a[j]) b[k++]=a[i++];
        else b[k++]=a[j++];
    }
    while(i<=mid) b[k++]=a[i++];
    while(j<=r) b[k++]=a[j++];
    for(int q=l; q<=r; q++) a[q]=b[q];
}

int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; i++) scanf("%lld",&a[i]);
    gsort(1,n);
    for(int i=1; i<=n; i++) printf("%lld ",a[i]);
    return 0;
}
View Code

2. P1439 【模板】最长公共子序列

直通

  我以前原来没做过qaq,这样的板子题。。意会了好久233

思路

  我们可以以第一个串为标准,用第二个串来匹配第一个串,看能匹配多少。

  所以,其实第一个串的每个数字其实影响不大,只有知道它对应了第二串的哪个数字就行,然后最后只要求一下上升序列就好辣~

代码酱qaq

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int M = 100010;
int n,len;
int a[M],b[M],belong[M];

int main() {
    scanf("%d",&n);
    //离散化一下 
    for(int i=1,x; i<=n; i++) {
        scanf("%d",&x);
        belong[x]=i;
    } 
    for(int i=1,x; i<=n; i++) {
        scanf("%d",&x);
        a[i]=belong[x];
    }
    for(int i=1; i<=n; i++) { //find上升序列 
        if(a[i]>b[len]) {
            b[++len]=a[i];
            continue;
        }
        int k=lower_bound(b+1,b+1+len,a[i])-b; 
        b[k]=a[i];
    }
    printf("%d\n",len);
    return 0;
}
View Code

3. P3390 【模板】矩阵快速幂

直通

今天刚学会qaq,考前的学新东西之一233

具体的嘛~我表示,只会背过+推矩阵

代码酱(*/ω\*)

#include <iostream>
#include <cstdio>
typedef long long LL;
using namespace std;

inline LL readl() {
    LL 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;
}

const int Mod = 1000000007;
LL n,m,i,j,k;
struct A {
    LL a[105][105];
    inline A operator * (const A &b) const {
        A ret;
        for(LL i=1; i<=n; i++)
            for(LL j=1; j<=n; j++) {
                ret.a[i][j]=0;
                for(LL k=1; k<=n; k++)
                    ret.a[i][j]+=a[i][k]*b.a[k][j],
                    ret.a[i][j]%=Mod;
            }
        return ret;
    }
}q;

A ksm(A a,LL x) {
    A ret,k;
    ret=a,k=a;
    x--;
    for(; x; x>>=1,k=k*k)
        if(x&1) ret=ret*k;
    return ret;
}

int main() {
    n=readl();m=readl();
    for(i=1; i<=n; i++)
        for(j=1; j<=n; j++)
            q.a[i][j]=readl();
    q=ksm(q,m);
    for(i=1; i<=n; i++) {
        for(j=1; j<n; j++) printf("%d ",q.a[i][j]);
        printf("%d\n",q.a[i][n]);
    }
    return 0;
}
View Code

4. P1939 【模板】矩阵加速(数列)

直通

思路

先看这个特征方程F[i] = F[i - 1] + F[i - 3],那么就有一个矩阵如下

我们的目标矩阵就是

那么,针对这个矩阵我们如何转置呢?

先看目标矩阵第一个:F[i]

F[i] = F[i - 1] + F[i - 3]

那么,由矩阵乘法,转置矩阵第一行,似乎就定了:1 0 1

同样的,二三行就是1 0 0 和 0 1 0

整个矩阵如下:

至于转置矩阵和初始矩阵的用法?

矩阵快速幂什么各种杂七杂八的

直通

代码酱_(:з」∠)_

#include <iostream>
#include <cstdio>
#define LL long long 
using namespace std;

inline LL read() {
    LL 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-48,c=getchar();
    return x*f;
}

const int Mod = 1000000007;
LL T,n;
struct Q {
    LL a[5][5];
    Q operator * (const Q &b) const {
        Q ret;
        for(int i=1; i<=3; i++) 
            for(int j=1; j<=3; j++) {
                ret.a[i][j]=0;
                for(int k=1; k<=3; k++) 
                    ret.a[i][j]+=a[i][k]*b.a[k][j];
                    ret.a[i][j]%=Mod;
            }
        return ret;
    }
}A,B;

inline Q ksm(Q A,LL x) {
    Q ret=A,k=A;
    x--;
    for(; x; x>>=1,k=k*k)
        if(x&1) ret=ret*k;
    return ret;
}

int main() {
    T=read();
    while(T--) {
        n=read();
        if(n<=3) {
            printf("1\n");
            continue;
        }
        else {
            A.a[1][1]=A.a[1][3]=A.a[2][1]=A.a[3][2]=1;
            A.a[1][2]=A.a[2][2]=A.a[2][3]=A.a[3][1]=A.a[3][3]=0;
            B.a[1][1]=B.a[1][2]=B.a[1][3]=1;
            Q P=ksm(A,n);
            printf("%lld\n",P.a[1][3]);
        }
    }
    return 0;
} 
View Code

5. P3367 【模板】并查集

直通

呼~今天刚整理了这个qaq,还好还有印象。。。

代码酱(≧▽≦)/

#include <iostream>
#include <cstdio>
using namespace std;

const int N = 10010;
int n,m;
int dad[N];

inline int getdad(int x) {
    return x == dad[x] ? x : dad[x]=getdad(dad[x]);
}

inline void Union(int u,int v) {
    int f1=getdad(u),f2=getdad(v);
    if(f1!=f2) dad[f1]=f2;
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++) dad[i]=i;
    for(int i=1,x,u,v; i<=m; i++) {
        scanf("%d%d%d",&x,&u,&v);
        if(x==1) {
            Union(u,v);
        }
        else {
            int f1=getdad(u),f2=getdad(v);
            if(f1!=f2) printf("N\n");
            else printf("Y\n");
        }
    }
    return 0;
}
View Code

6. P3372 【模板】线段树 1

直通

坑点

第一次交上竟然WA了qaq,我我我我原来是更新区间的时候忘记乘以长度了qaq,再犯蠢就打我自己qaq

代码酱(╥╯^╰╥)

#include <iostream>
#include <cstdio>
#define mid ((l+r)>>1)
#define lson rt<<1
#define rson rt<<1|1
#define LL long long
using namespace std;

const int M = 100001;
int n,m,a,b,x,s[M];
LL ans;
struct Tree {
    LL l,r,w,f;
} t[M<<2];

inline void update(int rt) {
    int l=t[rt].l,r=t[rt].r;
    t[rt].w=t[lson].w+t[rson].w;
}

inline void build(int rt,int l,int r) {
    t[rt].l=l,t[rt].r=r,t[rt].f=0;
    if(l==r) {
        t[rt].w=s[l];
        return ;
    }
    build(lson,l,mid);
    build(rson,mid+1,r);
    update(rt);
}

inline void down(int rt) {
    int l=t[rt].l,r=t[rt].r;
    t[lson].f+=t[rt].f;
    t[rson].f+=t[rt].f;
    t[lson].w+=t[rt].f*(t[lson].r-t[lson].l+1);
    t[rson].w+=t[rt].f*(t[rson].r-t[rson].l+1);
    t[rt].f=0;
}

inline void addq(int rt) {
    int l=t[rt].l,r=t[rt].r;
    if(a<=l && r<=b) {
        t[rt].f+=x;
        t[rt].w+=(t[rt].r-t[rt].l+1)*x;
        return ;
    }
    if(t[rt].f) down(rt);
    if(a<=mid) addq(lson);
    if(b>mid) addq(rson);
    update(rt);
}

inline void asksum(int rt) {
    int l=t[rt].l,r=t[rt].r;
    if(a<=l && r<=b) {
        ans+=t[rt].w;
        return ;
    }
    if(t[rt].f) down(rt);
    if(a<=mid) asksum(lson);
    if(b>mid) asksum(rson);
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++) scanf("%lld",&s[i]);
    build(1,1,n);
    for(int i=1,q; i<=m; i++) {
        scanf("%d",&q);
        if(q==1) {
            scanf("%d%d%d",&a,&b,&x);
            addq(1);
        }
        else {
            scanf("%d%d",&a,&b);
            asksum(1);
            printf("%lld\n",ans);
            ans=0;
        }
    }
    return 0;
}
View Code

7. P3366 【模板】最小生成树

直通

坑点 n,m顺序。。。

代码酱(・∀・)

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 5050;
const int M = 200020;
int n,m,ans;
int dad[N];
struct A {
    int u,v,w;
    bool operator < (const A &qwq) const {
        return w < qwq.w;
    }
}e[M];

int getdad(int x) {
    return x == dad[x] ? x : dad[x]=getdad(dad[x]);
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++) dad[i]=i; 
    for(int i=1; i<=m; i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    sort(e+1,e+m+1); //m!!!
    for(int i=1; i<=m; i++) {
        int f1=getdad(e[i].u),
            f2=getdad(e[i].v);
        if(f1!=f2) {
            dad[f1]=f2;
            ans+=e[i].w;
        }
    }
    int tmp=getdad(1);
    for(int i=1; i<=n; i++)
        if(getdad(i)!=tmp) {
            printf("orz");
            return 0;
        }
    printf("%d",ans);
    return 0;
}
View Code

8. P3375 【模板】KMP字符串匹配

直通

麻吉一A开熏qaq

代码酱(:3_ヽ)_

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int M = 1000010;
char s[M],p[M];
int lens,lenp;
int nxt[M];

void getnxt() {
    nxt[0]=-1,nxt[1]=0;
    int k=0,j=1;
    while(j<lenp) {
        if(k==-1 || p[k]==p[j]) {
            k++,j++;
            nxt[j]=k;
        } else k=nxt[k];
    }
}

void KMP() {
    int i=0,j=0;
    while(i<lens) {
        if(s[i]==p[j]) i++,j++;
        else if(j>=0) j=nxt[j];
        else i++,j=0;
        if(j==lenp) {
            int ans=i-j+1;
            printf("%d\n",ans);
        }
    }
}

int main() {
    cin>>s;lens=strlen(s);
    cin>>p;lenp=strlen(p);
    getnxt();
    KMP();
    for(int i=1; i<=lenp; i++) printf("%d ",nxt[i]);
    return 0;
}
View Code

9. P3371 【模板】单源最短路径

直通

新学到dijkstra!!!防止spfa被卡。。。

dijkstra大法好!priority_queue大法好!

代码酱。◕ᴗ◕。

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

const int INF = 2147483647;
const int N = 10010;
const int M = 500050;
struct rp {
    int next,to,w;
} e[M];
int top,head[N];
void add(int u,int v,int w) {
    top++;
    e[top].to=v;
    e[top].w=w;
    e[top].next=head[u];
    head[u]=top;
}
int n,m,s;
int dis[N],vis[N];
struct node {
    int x,dis;
    bool operator < (node a) const {
        return dis > a.dis;
    }
};

void spfa(int x) {
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[x]=0;vis[x]=1;
    queue<int>que;
    que.push(x);
    int u,v;
    while(!que.empty()) {
        u=que.front();que.pop();
        for(int i=head[u]; i; i=e[i].next) {
            v=e[i].to;
            if(dis[v]>dis[u]+e[i].w) {
                dis[v]=dis[u]+e[i].w;
                if(!vis[v]) {
                    vis[v]=1;
                    que.push(v);
                }
            }
        }
        vis[u]=0; 
    }
}

void dijkstra(int x) {
    priority_queue<node>q;
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[x]=0;
    q.push((node){x,0});
    while(!q.empty()) {
        node u=q.top();q.pop();
        if(vis[u.x]) continue;
        vis[u.x]=1;
        for(int i=head[u.x]; i; i=e[i].next) {
            int v=e[i].to;
            if(dis[v]>dis[u.x]+e[i].w) {
                dis[v]=dis[u.x]+e[i].w;
                q.push((node){v,dis[v]});
            }
        }
    }
}


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(u,v,w);
    }
//    spfa(s);
    dijkstra(s);
    for(int i=1; i<=n; i++)
        if(dis[i]==0x3f3f3f3f) printf("%d ",INF);
        else printf("%d ",dis[i]);
    return 0;
}
View Code

10.P3383 【模板】线性筛素数

直通

表示第一次交RE。。。找了一下原来是筛素数的时候i*prime[j]写成了j*prime[j]。。。蠢死了

代码酱(;д;)

#include <iostream>
#include <cstdio>
using namespace std;

const int N = 10000010;
int n,m,cnt;
int prime[N>>1],vis[N];
void getprime() {
    vis[0]=vis[1]=1;
    for(int i=2; i<=n; i++) {
        if(!vis[i]) prime[++cnt]=i;
        for(int j=1; j<=cnt && i*prime[j]<=n; j++) { //就这里qaq 
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}

int main() {
    scanf("%d%d",&n,&m);
    getprime();
    for(int i=1,x; i<=m; i++) {
        scanf("%d",&x);
        if(!vis[x]) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
View Code

11.P3378 【模板】堆

直通

嗦一下:STL大法好!!!

代码酱(❁´ω`❁)

#include <iostream>
#include <cstdio>
#include <queue> //使用堆(优先队列)的头文件
using namespace std;

int n;
priority_queue<int,vector<int>,greater<int> >q;
//小根堆...
//大根堆长这样->priority_queue<int>que; 

int main() {
    scanf("%d",&n);
    for(int i=1,p,x; i<=n; i++) {
        scanf("%d",&p);
        if(p==1) {
            scanf("%d",&x);
            q.push(x);
        }
        else if(p==2) printf("%d\n",q.top());
        else q.pop();
    }
    return 0;
}
View Code

12.P3370 【模板】字符串哈希 

直通

哇!刚在网上找到一个写的炒鸡漂漂滴模板,赶紧敲了一下!!!超满意!!!

代码酱(๑¯∀¯๑)

①刚学的!(作死)

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

const int size = 15000;
int n,cnt=0;
string tmp,hash[size];

int calc(string& x) {
    int ret=0;
    for(int i=0; i<x.length(); i++) 
        ret=(ret*256+x[i]+128)%size;
    return ret;
}

bool search(string& x,int& pos) {
    pos=calc(x);
    while(hash[pos]!="" && hash[pos]!=x) 
        pos=(pos+1)%size;
    if(hash[pos]==x) return true;
    else return false;
}

int Insert(string& x) {
    int pos;
    if(search(x,pos)) return 0;
    else {
        hash[pos]=x;
        return 1;
    }
}

int main() {
    cin>>n;
    for(int i=0; i<n; i++) {
        cin>>tmp;
        cnt+=Insert(tmp);
    } 
    cout<<cnt<<endl;
    return 0; 
} 
View Code

②以前的巨丑代码

#include <iostream>
#include <cstdio>
#include <set>
#include <cstring>
#include <algorithm>
using namespace std;

typedef unsigned long long ull;
typedef long long LL;
set<ull>ssr;

const int N = 2333;
const int D = 131;
const ull Mod = 1e9+7;
LL n,len;
string s;
ull f[N],g[N];

void pre(int m) {
    memset(f,0,sizeof(f));
    memset(g,0,sizeof(g));
    f[0]=s[0];
    for(int i=1; i<=m; i++)
        f[i]=(1LL*f[i-1]*D+s[i-1])%Mod;
    g[0]=1;
    for(int i=1; i<=m; i++)
        g[i]=1LL*g[i-1]*D%Mod;
}

int Hash(int l,int r) {
    ull a=f[r];
    ull b=1LL*f[l-1]*g[r-l+1]%Mod;
    return (a-b+Mod)%Mod;
}

int main() {
    cin>>n;
    while(n--) {
        cin>>s;
        len=s.length();
        pre(len);
        ull q=Hash(1,len);
        ssr.insert(q);
    }
    cout<<ssr.size();
    return 0;
}
View Code

13.P3379 【模板】最近公共祖先(LCA)

直通

代码酱o( =•ω•= )m

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;

const int M = 500050;
int n,m,s,p,num;
int dep[M],jumps[M][21];
int top,head[M];
bool vis[M];
struct A {
    int next,to;
} e[M<<1];
void add(int u,int v) {
    top++;
    e[top].to=v;
    e[top].next=head[u];
    head[u]=top;
}

void Dfs(int u) {
    for(int i=head[u],v; i; i=e[i].next) {
        v=e[i].to;
        if(dep[v]==0) {
            dep[v]=dep[u]+1;
            jumps[v][0]=u;
            Dfs(v);
        }
    }
}

void getstep() {
    for(int i=1; i<=20; i++)
        for(int j=1; j<=n; j++)
            jumps[j][i]=jumps[jumps[j][i-1]][i-1];
}

int LCA(int a,int b) {
    if(dep[a]<dep[b]) swap(a,b);
    for(int i=20; i>=0; i--)
        if(dep[jumps[a][i]]>=dep[b])
            a=jumps[a][i];
    if(a==b) return b;
    for(int i=20; i>=0; i--)
        if(jumps[a][i]!=jumps[b][i])
            a=jumps[a][i],b=jumps[b][i];
    return jumps[a][0];
}

int main() {
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1,u,v; i<n; i++) {
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    dep[s]=1;
    Dfs(s);
    getstep();
    int a,b;
    while(m--) {
        scanf("%d%d",&a,&b);
        printf("%d\n",LCA(a,b));
    }
    return 0;
}
View Code

 

 

 

 

 

 

 

 

表情包们

o( =•ω•= )m

٩(๑`^´๑)۶

(:3▓▒

ヾ(o◕∀◕)ノヾ

= ̄ω ̄=

n(*≧▽≦*)n

(๑´ㅂ`๑)ε

≡٩(๑>₃<)۶

*✧⁺˚⁺ପ(๑・ω・)੭ु⁾⁾ 

*:ஐ٩(๑´ᵕ`)۶ஐ:*

(っ•̀ω•́)っ✎⁾⁾ 

٩꒰▽ ꒱۶⁼³₌₃ 

…φ(๑˃∀˂๑)♪ 

(๑╹ヮ╹๑)ノ 

ヾヾ( ˘ ³˘人)ヾ

٩(๑❛ᴗ❛๑)۶

ヾ(❀●◡●)ノ

(  ー̀ωー́ )⊃⌒

φ(>ω<*) 

(。・ω・。)

(*・ω-q) 

(〃´-ω・)

 (>ω・* )ノ

( • ̀ω•́ )✧

(=・ω・=)o 

(=´ω`=)

d(´ω`*)

( ・´ω`・ )

(๑>ڡ<)☆

ヾ(◍°∇°◍)ノ゙

ヾ(๑╹◡╹)ノ"

⁄(⁄⁄•⁄ω⁄•⁄⁄)⁄

(..›ᴗ‹..)

(づ◡ど)

(ฅ'ω'ฅ)♪

(ミ´ω`ミ)

ฅ(*`ω´*)ฅ

 

posted @ 2017-11-10 09:15  夜雨声不烦  阅读(648)  评论(5编辑  收藏  举报