首页 > 技术文章 > 从2017年暑假到现在手打的模板↑_↑

fushao2yyj 2018-01-18 18:39 原文

Helloworld,我是来自湖南长沙的一枚蒟蒻,一个普通学生。(还有,我是男生).

从2017年暑假开始,我才接触了c++这种语言,觉得很美妙,有一种无所不能的感觉。

曾经,我只是接触过一部分这一类型的东东,也曾编程制作任务型和对抗型机器人(botball).

希望自己能结合曾经的浅薄知识,对信息学有更深的认识,认真学习!

很乐意交友,很乐意与大家交流学习哦。

以下都是我学到的部分知识,大部分学自他人的博客,真的很感激各路大神。

所以,我也十分乐意分享自己学习算法的理解和心得,希望大家多多关注!(关爱菜鸡,人人有责).

 

一、

求逆元-费马小定理

#include <bits/stdc++.h>
using namespace std;
typedef long long lol;

int n,p;

lol qpow(lol x)
{
    int y=p-2;
    lol ans=1;
    while (y) {
        if (y&1) ans*=x,ans%=p;
        x*=x;x%=p;y/=2;
    }
    return ans;
}

inline void write(lol x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}

int main()
{
    scanf("%d%d",&n,&p);
    for (int i=1;i<=n;i++) {
        write(qpow(i)%p);
        putchar('\n');
    }
    return 0;
}
View Code

 

二、

树状数组

#include <bits/stdc++.h>
using namespace std;
typedef long long lol;

lol n,m;
lol f[500010];

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

void add(lol x,lol k)
{
    for (int i=x;i<=n;i+=lowbit(i)) f[i]+=k;
}

lol getsum(lol x)
{
    lol ans=0;
    for (int i=x;i;i-=lowbit(i)) ans+=f[i];
    return ans;
}

int main()
{
    cin>>n>>m;lol a;
    for (int i=1;i<=n;i++) scanf("%lld",&a),add(i,a);
    lol flag,x,y,k;
    for (int i=1;i<=m;i++) {
        scanf("%lld%lld",&flag,&x);
        if (flag==1) {
            scanf("%lld",&k);
            add(x,k);
        }
        if (flag==2) {
            scanf("%lld",&y);
            printf("%lld\n",getsum(y)-getsum(x-1));
        }
    }
    return 0;
}
View Code

 

三、

最大流-Dinic

#include <bits/stdc++.h>
using namespace std;

int cnt=-1,depth[10010],cur[10010],s,t,n,m;
int next[200010],head[10010],v[200010],w[200010];

int dfs(int u,int flow)
{
    if (u==t) return flow;
    for (int& i=cur[u];i!=-1;i=next[i]) {
        if ((w[i]!=0)&&(depth[v[i]]==depth[u]+1)) {
            int di=dfs(v[i],min(flow,w[i]));
            if (di>0) {w[i]-=di;w[i^1]+=di;return di;}
        }
    }
    return 0;
}

bool bfs()
{
    queue <int> q;
    memset(depth,0,sizeof(depth));
    while (!q.empty()) q.pop();
    q.push(s);depth[s]=1;
    do {
        int u=q.front();q.pop();
        for (int i=head[u];i!=-1;i=next[i]) {
            if ((w[i]>0)&&(depth[v[i]]==0)) {
                q.push(v[i]);depth[v[i]]=depth[u]+1;
            }
        }
    }while(!q.empty());
    if (depth[t]>0) return 1;
    return 0;
}

int dinic()
{
    int ans=0;
    while (bfs()) {
        for (int i=1;i<=n;i++) cur[i]=head[i];
        while (int d=dfs(s,3e8)) ans+=d;
    }
    return ans;
}

int main()
{
    int a,b,c;
    cin>>n>>m>>s>>t;
    memset(head,-1,sizeof(head));
    memset(next,-1,sizeof(next));
    while (m--) {
        scanf("%d%d%d",&a,&b,&c);
        cnt++;v[cnt]=b;w[cnt]=c;
        next[cnt]=head[a];head[a]=cnt;
        cnt++;v[cnt]=a;w[cnt]=0;
        next[cnt]=head[b];head[b]=cnt;
    }
    cout<<dinic()<<endl;
    return 0;
}
View Code

 

四、

二分图-匈牙利算法

#include <bits/stdc++.h>
using namespace std;

int n,m,e,girl[1005];
bool used[1005],line[1005][1005];

bool find(int x)
{
    for (int j=1;j<=m;j++)
    if (line[x][j]&&!used[j]) {
        used[j]=1;
        if (!girl[j]||find(girl[j])) {
            girl[j]=x;return 1;
        }
    }
    return 0;
}

int main()
{
    int x,y;
    cin>>n>>m>>e;
    for (int i=1;i<=e;i++)
    scanf("%d%d",&x,&y),line[x][y]=1;
    e=0;
    for (int i=1;i<=n;i++) {
        if (find(i)) e++;
        memset(used,0,sizeof(used));
    }
    cout<<e<<endl;
    return 0;
}
View Code

 

五、

扩展欧几里得

#include <bits/stdc++.h>
using namespace std;

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

int main()
{
    int a,b,x,y;
    cin>>a>>b;
    exgcd(a,b,x,y);
    cout<<(x%b+b)%b<<endl;
    return 0;
}
View Code

 

六、

假的字符串Hash,其实是map

#include <bits/stdc++.h>
using namespace std;

int n;
string s;
map <string,int> mp;

int main()
{
    cin>>n;int ans=0;
    for (int i=1;i<=n;i++) {
        cin>>s;
        if (!mp.count(s)) ans++,mp[s]=1;
    }
    cout<<ans<<endl;
    return 0;
}
View Code

 

七、

克鲁斯卡尔

#include <bits/stdc++.h>
using namespace std;

int n,m;
int fa[5001];

struct ed {
    int f,t,w;
}e[400010];

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

void init()
{
    for (int i=1;i<=n;i++) fa[i]=i;
}

int find(int a)
{
    if (a==fa[a]) return a;
    return fa[a]=find(fa[a]);
}

void unionset(int a,int b)
{
    int u=find(a),v=find(b);
    if (u!=v) fa[u]=v;
}

bool same(int u,int v)
{
    return find(u)==find(v);
}

void kruskal()
{
    int res=0;
    init();int cnt=0;
    sort(e+1,e+1+m,cmp);
    for (int i=1;i<=m;i++) {
        if (!same(e[i].f,e[i].t)) {
            res+=e[i].w;
            unionset(e[i].f,e[i].t);
            ++cnt;
        }
        if (cnt==n-1) break;
    }
    cout<<res<<endl;
}

int main()
{
    cin>>n>>m;int x,y,w;
    for (int i=1;i<=m;i++) {
        scanf("%d%d%d",&x,&y,&w);
        e[i].f=x;e[i].t=y;e[i].w=w;
    }
    kruskal();
    return 0;
}
View Code

 

八、

LCA-倍增

#include <bits/stdc++.h>
using namespace std;

int n,m,ss;
int dep[500010];
int dpt[500010][30];
int cnt;
int o[1000010];
int s[1000010][2];

void jia(int x,int y)
{
    s[++cnt][1]=o[x];
    s[cnt][0]=y;o[x]=cnt;
}

void dfs(int x,int d)
{
    dep[x]=d;
    for (int i=o[x];i;i=s[i][1]) {
        int y=s[i][0];
        if (!dep[y]) {
            dpt[y][0]=x;
            dfs(y,d+1);
        }
    }
}

void init()
{
    for (int j=1;j<=19;j++)
    for (int i=1;i<=n;i++)
    dpt[i][j]=dpt[dpt[i][j-1]][j-1];
}

int lca(int a,int b)
{
    if (dep[a]<dep[b]) swap(a,b);
    for (int j=19;j>=0;j--)
    if (dep[a]-(1<<j)>=dep[b]) a=dpt[a][j];
    if (a!=b) {
        for (int j=19;j>=0;j--)
        if (dpt[a][j]!=dpt[b][j])
        a=dpt[a][j],b=dpt[b][j];
        a=dpt[a][0];
    }
    return a;
}

int main()
{
    int x,y;
    cin>>n>>m>>ss;
    for (int i=1;i<n;i++) {
        scanf("%d%d",&x,&y);
        jia(x,y);jia(y,x);
    }
    dfs(ss,1);init();
    for (int i=1;i<=m;i++) {
        scanf("%d%d",&x,&y);
        printf("%d\n",lca(x,y));
    }
    return 0;
}
View Code

 

九、

最长公共子序列(离散+LIS法求LCS)

#include <bits/stdc++.h>
#define N 100010
using namespace std;

int len,b[N],f[N];
int n,table[N],in[N];

int main()
{
    int a;
    cin>>n;
    for (int i=1;i<=n;i++) {
        scanf("%d",&a);
        table[a]=i;
    }
    for (int i=1;i<=n;i++)
    scanf("%d",&in[i]);
    for (int i=1;i<=n;i++) {
        if (table[in[i]]>b[len]) {
            b[++len]=table[in[i]];
            f[i]=len;
            continue;
        }
        int arr=lower_bound(b+1,b+1+len,table[in[i]])-b;
        b[arr]=table[in[i]];
        f[i]=arr;
    }
    cout<<len<<endl;
    return 0;
}
View Code

 

十、

归并排序求逆序对

#include <bits/stdc++.h>
using namespace std;

int ans,n,a[100010],r[100010];

void msort_nxd(int s,int t)
{
    if (s==t) return;
    int mid=s+t>>1;
    msort_nxd(s,mid);
    msort_nxd(mid+1,t);
    int i=s,j=mid+1,k=s;
    while (i<=mid&&j<=t) {
        if (a[i]<=a[j]) {
            r[k]=a[i];i++;k++;
        }
        else {
            r[k]=a[j];j++;k++;
            ans+=mid-i+1;
        }
    }
    while (i<=mid) r[k++]=a[i++];
    while (j<=t) r[k++]=a[j++];
    for (int q=s;q<=t;q++) a[q]=r[q];
}

int main()
{
    cin>>n;
    for (int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
    }
    msort_nxd(1,n);
    cout<<ans<<endl;
    return 0;
}
View Code

 

十一、

线段树

#include <bits/stdc++.h>
#define ll(x) ((x)<<1)
#define rr(x) ((x)<<1|1)
using namespace std;
typedef long long lol;

lol n,m,a[100010];
lol sgm[100010*4],lazy[100010*4];

void shang(lol r)
{
    sgm[r]=sgm[ll(r)]+sgm[rr(r)];
}

void xia(lol r,lol z,lol y)
{
    int k=z+y>>1;
    lazy[ll(r)]+=lazy[r];
    lazy[rr(r)]+=lazy[r];
    sgm[ll(r)]+=(k-z+1)*lazy[r];
    sgm[rr(r)]+=(y-k)*lazy[r];
    lazy[r]=0;
}

void js(lol r,lol z,lol y)
{
    if (z==y) {
        sgm[r]=a[z];
        return;
    }
    int k=z+y>>1;
    js(ll(r),z,k);
    js(rr(r),k+1,y);
    shang(r);
}

void qjxg(lol r,lol z,lol y,lol zz,lol yy,lol v)
{
    if (z>yy||y<zz) return;
    if (z>=zz&&y<=yy) {
        lazy[r]+=v;
        sgm[r]+=(y-z+1)*v;
        return;
    }
    if (lazy[r]) xia(r,z,y);
    int k=z+y>>1;
    if (zz<=k) qjxg(ll(r),z,k,zz,yy,v);
    if (yy>k) qjxg(rr(r),k+1,y,zz,yy,v);
    shang(r);
}

lol cx(lol r,lol z,lol y,lol zz,lol yy)
{
    if (z>yy||y<zz) return 0;
    if (z>=zz&&y<=yy) return sgm[r];
    int k=z+y>>1;
    if (lazy[r]) xia(r,z,y);
    return cx(ll(r),z,k,zz,yy)+cx(rr(r),k+1,y,zz,yy);
}

int main()
{
    cin>>n>>m;
    for (int i=1;i<=n;i++) {
        scanf("%lld",&a[i]);
    }
    js(1,1,n);
    lol flag,x,y,k;
    for (int i=1;i<=m;i++) {
        scanf("%lld",&flag);
        if (flag==1) {
            scanf("%lld%lld%lld",&x,&y,&k);
            qjxg(1,1,n,x,y,k);
        }
        else {
            scanf("%lld%lld",&x,&y);
            cout<<cx(1,1,n,x,y)<<endl;
        }
    }
    return 0;
}
View Code

 

十二、

 SPFA

#include <bits/stdc++.h>
using namespace std;

int n,m,st,d[10010];
int cnt;
int o[500010];
int s[500010][3];

void jia(int x,int y,int c)
{
    s[++cnt][1]=o[x];
    s[cnt][0]=y;
    s[cnt][2]=c;o[x]=cnt;
}

queue <int> q;
bool v[10010];

void SPFA()
{
    for (int i=1;i<=n;i++)
    d[i]=2147483647;
    v[st]=1;q.push(st);d[st]=0;
    while (!q.empty()) {
        int x=q.front();
        for (int i=o[x];i;i=s[i][1]) {
            int y=s[i][0];
            if (d[y]>d[x]+s[i][2]) {
                d[y]=d[x]+s[i][2];
                if (!v[y]) {
                    v[y]=1;
                    q.push(y);
                }
            }
        }
        q.pop();v[x]=0;
    }
}

int main()
{
    int x,y,c;
    cin>>n>>m>>st;
    for (int i=1;i<=m;i++) {
        scanf("%d%d%d",&x,&y,&c);
        jia(x,y,c);
    }
    SPFA();
    for (int i=1;i<=n;i++) {
        printf("%d ",d[i]);
    }
    cout<<endl;
    return 0;
}
View Code

 

 十三、

树链剖分

#include <bits/stdc++.h>
#define ll(x) ((x)<<1)
#define rr(x) ((x)<<1|1)
using namespace std;
typedef long long l;

const int N=100010;l n,m,r,p,cnt,dfscnt;
l d[N],id[N],f[N],son[N],top[N],siz[N],sgm[N*4],lazy[N*4],a[N],w[N],o[N],s[N*2][2];

void jia(l x,l y) {s[++cnt][1]=o[x];s[cnt][0]=y;o[x]=cnt;}

void dfs(l x,l fa,l dep)
{
    f[x]=fa;d[x]=dep;siz[x]=1;l mm=-1;
    for (int i=o[x];i;i=s[i][1]) {
        if (s[i][0]!=fa) {
            dfs(s[i][0],x,dep+1);siz[x]+=siz[s[i][0]];
            if (siz[s[i][0]]>mm) son[x]=s[i][0],mm=siz[s[i][0]];
        }
    }
}

void build(l x,l tp)
{
    id[x]=++dfscnt;top[x]=tp;a[dfscnt]=w[x];
    if (son[x]) build(son[x],tp);
    for (int i=o[x];i;i=s[i][1])
    if ((s[i][0]!=f[x])&&(son[x]!=s[i][0])) build(s[i][0],s[i][0]);
}

void xia(l r,l z,l y)
{
    l k=z+y>>1;lazy[ll(r)]+=lazy[r];lazy[rr(r)]+=lazy[r];
    sgm[ll(r)]+=(k-z+1)*lazy[r];
    sgm[rr(r)]+=(y-k)*lazy[r];
    sgm[ll(r)]%=p;sgm[ll(r)]%=p;lazy[r]=0;
}

void js(l r,l z,l y)
{
    if (z==y) {sgm[r]=a[z];if (sgm[r]>p) sgm[r]%=p;return;}
    l k=z+y>>1;js(ll(r),z,k);js(rr(r),k+1,y);sgm[r]=(sgm[ll(r)]+sgm[rr(r)])%p;
}

void qjxg(l r,l z,l y,l zz,l yy,l v)
{
    if (z>yy||y<zz) return;
    if (z>=zz&&y<=yy) {
        lazy[r]+=v;sgm[r]+=(y-z+1)*v;return;}
    if (lazy[r]) xia(r,z,y);l k=z+y>>1;
    if (zz<=k) qjxg(ll(r),z,k,zz,yy,v);if (yy>k) qjxg(rr(r),k+1,y,zz,yy,v);
    sgm[r]=(sgm[ll(r)]+sgm[rr(r)])%p;
}

l cx(l r,l z,l y,l zz,l yy)
{
    if (z>yy||y<zz) return 0;
    if (z>=zz&&y<=yy) return sgm[r]%p;
    l k=z+y>>1;if (lazy[r]) xia(r,z,y);
    return (cx(ll(r),z,k,zz,yy)+cx(rr(r),k+1,y,zz,yy))%p;
}

l qiulu(l x,l y)
{
    l ans=0;while (top[x]!=top[y]) {
        if (d[top[x]]<d[top[y]]) swap(x,y);
        ans+=cx(1,1,n,id[top[x]],id[x]);ans%=p;x=f[top[x]];
    }
    if (d[x]>d[y]) swap(x,y);ans+=cx(1,1,n,id[x],id[y]);ans%=p;
    return ans;
}

void jialu(l x,l y,l v)
{
    v%=p;while (top[x]!=top[y]) {
        if (d[top[x]]<d[top[y]]) swap(x,y);
        qjxg(1,1,n,id[top[x]],id[x],v);x=f[top[x]];
    }
    if (d[x]>d[y]) swap(x,y);qjxg(1,1,n,id[x],id[y],v);
}

int main()
{
    l x,y,v,flag;cin>>n>>m>>r>>p;for (int i=1;i<=n;i++) scanf("%lld",&w[i]);
    for (int i=1;i<n;i++) {scanf("%lld%lld",&x,&y);jia(x,y);jia(y,x);}dfs(r,0,1);build(r,r);js(1,1,n);
    for (int i=1;i<=m;i++) {scanf("%lld",&flag);
        if (flag==1) {scanf("%lld%lld%lld",&x,&y,&v);jialu(x,y,v);}
        if (flag==2) {scanf("%lld%lld",&x,&y);printf("%lld\n",qiulu(x,y));}
        if (flag==3) {scanf("%lld%lld",&x,&v);v%=p;qjxg(1,1,n,id[x],id[x]+siz[x]-1,v);}
        if (flag==4) {scanf("%lld",&x);printf("%lld\n",cx(1,1,n,id[x],id[x]+siz[x]-1)%p);}
    }
    return 0;
}
View Code

 

 十四、

最小费用最大流

#include <bits/stdc++.h>
using namespace std;

const int N=5010,M=100010,inf=2e9;
int head,tail,cnt=-1,n,m,s,t,cost=0;
int q[N*10],v[N],ss[M*2][4],o[N],d[N],vis[N];

void jia(int a,int b,int c,int cc)
{
    ss[++cnt][0]=b;ss[cnt][1]=o[a];
    ss[cnt][2]=c;ss[cnt][3]=cc;o[a]=cnt;
    ss[++cnt][0]=a;ss[cnt][1]=o[b];
    ss[cnt][2]=0;ss[cnt][3]=-cc;o[b]=cnt;
}

int dfs(int x,int flow)
{
    v[x]=1;int rest=0;if (x==t) return flow;
    for (int i=o[x];i!=-1;i=ss[i][1]) {
        if ((d[ss[i][0]]==d[x]-ss[i][3])&&(v[ss[i][0]]==0)&&(ss[i][2]!=0)) {
            int di=dfs(ss[i][0],min(flow-rest,ss[i][2]));
            if (di>0) {rest+=di;ss[i][2]-=di;ss[i^1][2]+=di;}
        }
    }
    return rest;
}

bool spfa()
{
    for (int i=1;i<=n;i++) d[i]=inf,vis[i]=0;
    head=1;tail=2;q[1]=t;d[t]=0;vis[t]=1;
    while (head!=tail) {
        int u=q[head];
        for (int i=o[u];i!=-1;i=ss[i][1]) {
            if ((d[ss[i][0]]>d[u]-ss[i][3])&&(ss[i^1][2]!=0)) {
                d[ss[i][0]]=d[u]-ss[i][3];
                if (!vis[ss[i][0]]) {
                    vis[ss[i][0]]=1;q[tail++]=ss[i][0];if (tail==n+1) tail=1;
                }
            }
        }
        q[head++]=0;vis[u]=0;if (head==n+1) head=1;
    }
    return d[s]!=inf;
}

void FU_DUI_SUAN_FA_BO_DA_JING_SHEN()
{
    int ans=0,cntt=1;
    while (spfa()) {
        v[t]=1;
        while (v[t]) {
            memset(v,0,sizeof(v));
            int l=dfs(s,inf);ans+=l;cost+=l*d[s];
        }
    }
    cout<<ans<<" "<<cost<<endl;
}

int main()
{
    int a,b,c,cc;
    memset(o,-1,sizeof(o));
    cin>>n>>m>>s>>t;
    for (int i=1;i<=m;i++) {
        scanf("%d%d%d%d",&a,&b,&c,&cc);
        jia(a,b,c,cc);
    }
    FU_DUI_SUAN_FA_BO_DA_JING_SHEN();
    return 0;
}
View Code

 

十五、

堆(手打)

#include <bits/stdc++.h>
using namespace std;

int n,flag,heap[1000010],heapsize;

void jiaru(int d)
{
    int now,next;heap[++heapsize]=d;now=heapsize;
    while (now>1) {
        next=now>>1;if (heap[now]>=heap[next]) break;
        swap(heap[now],heap[next]);now=next;
    }
    return;
}

int shanchu_quchu()
{
    int now,next,res;res=heap[1];heap[1]=heap[heapsize--];now=1;
    while (now*2<=heapsize) {
        next=now*2;
        if (next<heapsize&&heap[next+1]<heap[next]) next++;
        if (heap[now]<=heap[next]) break;swap(heap[now],heap[next]);
        now=next;
    }
    return res;
}

int main()
{
    cin>>n;int x;
    while (n--) {
        scanf("%d",&flag);
        if (flag==1) {scanf("%d",&x);jiaru(x);}
        if (flag==2) {printf("%d\n",heap[1]);}
        if (flag==3) {int daiti=shanchu_quchu();}
    }
    return 0;
}
View Code

 

十六、

优先队列(STL)

#include <bits/stdc++.h>
using namespace std;

int n,flag,a;
priority_queue <int> heap;

int main() {
    cin>>n;
    for (int i=1;i<=n;i++) {
        cin>>flag;
        if (flag==1) {
            cin>>a;
            heap.push(-a);
        }
        else if (flag==2) {
            int f=heap.top();
            cout<<-f<<endl;
        }
        else heap.pop();
    }
    return 0;
}
View Code

 

十七、

迪杰斯特拉(堆优化版本)

#include <bits/stdc++.h>
#define MAXN 10010
using namespace std;
typedef pair<int,int>Pair;

struct node {
  int u,w,v,next;
}e[500010];

int dis[MAXN],st[MAXN];
bool flag[MAXN];
int tot,start,n,m,x,y,z;

void add(int x,int y,int z)
{
  e[++tot].u=x;e[tot].v=y;
  e[tot].w=z;
  e[tot].next=st[x];st[x]=tot;
}

int dijsktra(int start)
{
  memset(dis,127,sizeof dis);
  memset(flag,0,sizeof flag);
  dis[start]=0;priority_queue< Pair,vector<Pair>,greater<Pair> >que;
  que.push(make_pair(dis[start],start));
  while (!que.empty()) {
    Pair now=que.top();que.pop();
    if (flag[now.second]) continue;
    flag[now.second]=1;
    for (int i=st[now.second];i;i=e[i].next)
    if (dis[now.second]+e[i].w<dis[e[i].v]) {
      dis[e[i].v]=dis[now.second]+e[i].w;
      if (!flag[e[i].v]) que.push(make_pair(dis[e[i].v],e[i].v));
    }
  }
  for (int i=1;i<=n;i++) {
    if (dis[i]==2139062143) dis[i]=2147483647;
    printf("%d ",dis[i]);
  }
}
int main()
{
  scanf("%d%d%d",&n,&m,&start);
  for (int i=1;i<=m;i++) {
    scanf("%d%d%d",&x,&y,&z);
    add(x,y,z);
  }
  dijsktra(start);
}
View Code

 

十八、

迪杰斯特拉(线段树版本)

#include <bits/stdc++.h>
using namespace std;

const int maxn =10007;
const int maxm = 500007;
const int INF = 0x7fffffff;
int n,m;

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

struct node{
  int v,next,w;
}edge[maxm];

int num=0,head[maxn];

inline void add_edge(int a,int b,int c) {
  edge[++num].v=b;edge[num].w=c;edge[num].next=head[a];head[a]=num;
}

int dis[maxn],ans[maxn],s,t;
int tree[maxn<<2],leaf;

inline int check(int i,int j) {
  return dis[i]<dis[j]?i:j;
}

inline void build() {
  std::memset(dis,0x3f,sizeof dis);
  for (leaf=1;leaf<=n;leaf<<=1);--leaf;
  for (int i=1;i<=n;++i)tree[leaf+i]=i;
}

inline void modify(int x,int y) {
  dis[x]=y,x+=leaf,x>>=1;
  while(x) tree[x]=check(tree[x<<1],tree[x<<1|1]),x=x>>1;
}

void dijkstra(int s) {
  build();dis[s]=0;int u=s;
  for (int i=1;i<=n;++i) {
    ans[u]=dis[u];
    const int disu=dis[u];
    modify(u,INF); 
    for (int j=head[u];j;j=edge[j].next){
      int v=edge[j].v;
      if (dis[v]<INF&&dis[v]>disu+edge[j].w)
        modify(v,disu+edge[j].w);
    }
    u=tree[1];
  }
}

inline void put(int x)
{
  if (x>9) put(x/10);
  putchar(x%10+48);   
}

int main() {
    int k;
    n=read(),m=read(),k=read();
    for (int a,b,c,i=1;i<=m;++i) {
        a=read(),b=read(),c=read();
        add_edge(a,b,c);
  }
  dijkstra(k);
  for (int i=1;i<=n;++i) {
    if (dis[i]==0x3f3f3f3f) ans[i]=INF;
      put(ans[i]);putchar(' ');
  }
  putchar('\n');
  return 0;
}
View Code

 

十九、

普通平衡树(splay)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=100010;
int ch[N][2],f[N],ky[N],ct[N],siz[N],sz,rt;

void clear(int x)
{
    ch[x][0]=ch[x][1]=f[x]=siz[x]=ct[x]=ky[x]=0;
    return;
}

bool get(int x)
{
    return ch[f[x]][1]==x;
}

void update(int x)
{
    if (x) {
        siz[x]=ct[x];
        if (ch[x][0]) siz[x]+=siz[ch[x][0]];
        if (ch[x][1]) siz[x]+=siz[ch[x][1]];
    }
    return;
}

void rotate(int x)
{
    int old=f[x],oldf=f[old],which=get(x);
    ch[old][which]=ch[x][which^1];f[ch[old][which]]=old;
    ch[x][which^1]=old;f[old]=x;f[x]=oldf;
    if (oldf) ch[oldf][ch[oldf][1]==old]=x;
    update(old);update(x);
}

void splay(int x)
{
    for (int fa;fa=f[x];rotate(x))
    if (f[fa]) rotate((get(x)==get(fa))?fa:x);
    rt=x;return;
}

void insert(int v)
{
    if (!rt) {
        sz++;ch[sz][0]=ch[sz][1]=f[sz]=0;
        ky[sz]=v;ct[sz]=1;siz[sz]=1;rt=sz;
        return;
    }
    int now=rt,fa=0;
    while (1) {
        if (ky[now]==v) {
            ct[now]++;
            update(now);update(fa);
            splay(now);break;
        }
        fa=now;now=ch[now][ky[now]<v];
        if (!now) {
            sz++;ch[sz][0]=ch[sz][1]=0;ky[sz]=v;siz[sz]=1;
            ct[sz]=1;f[sz]=fa;ch[fa][ky[fa]<v]=sz;
            update(fa);splay(sz);break;
        }
    }
    return;
}

int find(int v)
{
    int ans=0,now=rt;
    while (1) {
        if (v<ky[now]) now=ch[now][0];
        else {
            ans+=(ch[now][0]?siz[ch[now][0]]:0);
            if (v==ky[now]) {splay(now);return ans+1;}
            ans+=ct[now];now=ch[now][1];
        }
    }
    return 0;
}

int findx(int x)
{
    int now=rt;
    while (1) {
        if (ch[now][0]&&x<=siz[ch[now][0]]) now=ch[now][0];
        else {
            int tt=(ch[now][0]?siz[ch[now][0]]:0)+ct[now];
            if (x<=tt) return ky[now];
            x-=tt;now=ch[now][1];
        }
    }
    return 0;
}

int pre()
{
    int now=ch[rt][0];
    while (ch[now][1]) now=ch[now][1];
    return now;
}

int next()
{
    int now=ch[rt][1];
    while (ch[now][0]) now=ch[now][0];
    return now;
}

void del(int x)
{
    int whatever=find(x);
    if (ct[rt]>1) {ct[rt]--;update(rt);return;}
    if (!ch[rt][0]&&!ch[rt][1]) {clear(rt);rt=0;return;}
    if (!ch[rt][0]) {
        int oldrt=rt;rt=ch[rt][1];f[rt]=0;clear(oldrt);return;
    }
    else if (!ch[rt][1]) {
        int oldrt=rt;rt=ch[rt][0];f[rt]=0;clear(oldrt);return;
    }
    int leftbig=pre(),oldrt=rt;
    splay(leftbig);
    ch[rt][1]=ch[oldrt][1];f[ch[oldrt][1]]=rt;
    clear(oldrt);update(rt);return;
}

int main()
{
    int n,a,b;cin>>n;int rrr=0;
    while (n--) {
        scanf("%d%d",&a,&b);
        if (a==1) insert(b)/*,cout<<++rrr<<"i"<<endl*/;
        else if (a==2) del(b)/*,cout<<++rrr<<"d"<<endl*/;
        else if (a==3) printf("%d\n",find(b))/*,cout<<++rrr<<"f"<<endl*/;
        else if (a==4) printf("%d\n",findx(b))/*,cout<<++rrr<<"x"<<endl*/;
        else if (a==5) {insert(b);printf("%d\n",ky[pre()]);del(b)/*,cout<<++rrr<<"p"<<endl*/;}
        else {insert(b);printf("%d\n",ky[next()]);del(b)/*,cout<<++rrr<<"n"<<endl*/;}
    }
    return 0;
}
View Code

 

二十、

矩阵快速幂

#include <bits/stdc++.h>
using namespace std;

long long n,p;
long long mod=1e9+7;
long long ans[105][105];
long long a[105][105],b[105][105];

void lu() {
    memcpy(b,ans,sizeof(ans));
    memset(ans,0,sizeof(ans));
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            for (int k=1;k<=n;k++)
                ans[i][j]=(ans[i][j]+(b[i][k]*a[k][j])%mod)%mod;
}

void ge() {
    memcpy(b,a,sizeof(a));
    memset(a,0,sizeof(a));
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            for (int k=1;k<=n;k++)
                a[i][j]=(a[i][j]+(b[i][k]*b[k][j])%mod)%mod;
}

int main() {
    cin>>n>>p;p--;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            cin>>ans[i][j];
    memcpy(a,ans,sizeof(a));
    while (p) {
        if (p&1) lu();
        ge();p>>=1;
    }
    for (int i=1;i<=n;i++) {
        for (int j=1;j<=n;j++)
            cout<<ans[i][j]<<' ';
        cout<<endl;
    }
    return 0;
}
View Code

 

二十一、

普通平衡树(treap)

#include <bits/stdc++.h>
using namespace std;

const int N=11e4,big=2e9;
int top,sz,ch[N][2],siz[N],rk[N],num[N],f[N],small=-big;

void update(int x)
{
    siz[x]=siz[ch[x][1]]+siz[ch[x][0]]+1;
    return;
}

int rotate(int j,int get)
{
    int nson=ch[j][get],other=(get^1);
    ch[j][get]=ch[nson][other];
    ch[nson][other]=j;
    update(j);update(nson);
    return nson;
}

int insert(int j,int v)
{
    if (!j) {
        sz++;siz[sz]=1;
        num[sz]=v;rk[sz]=rand();
        return sz;
    }
    bool get=(num[j]<=v);
    siz[j]++;ch[j][get]=insert(ch[j][get],v);
    if (rk[j]>rk[ch[j][get]]) return rotate(j,get);
    return j;
}

int del(int j,int v)
{
    if (num[j]==v) {
        if (ch[j][0]&&ch[j][1]) {
            int son=ch[j][0],fa=0;
            while (ch[son][1]) fa=son,son=ch[son][1],siz[fa]--;
            if (son==ch[j][0]) {
                ch[son][1]=ch[j][1];rk[son]=rk[j];
                siz[son]=siz[j]-1;return son;
            }
            ch[fa][1]=ch[son][0];ch[son][0]=ch[j][0];
            ch[son][1]=ch[j][1];rk[son]=rk[j];siz[son]=siz[j]-1;
            return son;
        }
        if (ch[j][0]) return ch[j][0];
        return ch[j][1];
    }
    int get=(num[j]<v);
    ch[j][get]=del(ch[j][get],v);siz[j]--;return j;
}

int newww(int j,int x)
{
    if (!j) return -1;
    if (num[j]==x) {
        int ans=newww(ch[j][0],x);
        return ans==-1?j:ans;
    }
    if (num[j]>x) return newww(ch[j][0],x);
    return newww(ch[j][1],x);
}

int find(int i,int j,int x)
{
    if (i==j) return siz[ch[i][0]]+1;
    if (num[i]>=x) return find(ch[i][0],j,x);
    return find(ch[i][1],j,x)+siz[ch[i][0]]+1;
}

int findx(int j,int x)
{
    if (siz[ch[j][0]]==x-1) return num[j];
    if (siz[ch[j][0]]>=x) return findx(ch[j][0],x);
    return findx(ch[j][1],x-siz[ch[j][0]]-1);
}

int pre(int j,int x)
{
    if (!j) return small;
    if (num[j]<x) return max(num[j],pre(ch[j][1],x));
    return pre(ch[j][0],x);
}

int next(int j,int x)
{
    if (!j) return big;
    if (num[j]>x) return min(num[j],next(ch[j][0],x));
    return next(ch[j][1],x);
}

int main()
{
    srand(time(NULL));
    int n,m,x;cin>>n;
    while (n--) {
        scanf("%d%d",&m,&x);
        if (m==1) top=insert(top,x);
        if (m==2) top=del(top,x);
        if (m==3) printf("%d\n",find(top,newww(top,x),x));
        if (m==4) printf("%d\n",findx(top,x));
        if (m==5) printf("%d\n",pre(top,x));
        if (m==6) printf("%d\n",next(top,x));
    }
    return 0;
}
View Code

 

二十二、

线性筛素数(欧拉筛)

#include <bits/stdc++.h>
using namespace std;

int n,m;
int prime[10000010];
bool isprime[10000010];
int primesize;

int gi() {
    char c=getchar();int a=0;bool f=0;
    while (c>'9'||c<'0') {if (c=='-') f=1;c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0';c=getchar();}
    return f?-a:a;
}

void shai(int listsize) {
    memset(isprime,true,sizeof(isprime));
    isprime[1]=false;
    for (int i=2;i<=listsize;i++) {
        if (isprime[i]) prime[++primesize]=i;
        for (int j=1;j<=primesize&&i*prime[j]<=listsize;j++) {
            isprime[i*prime[j]]=false;
            if (i%prime[j]==0) break;
        }
    }
}

int main() {
    n=gi();m=gi();
    shai(n);
    for (int i=1;i<=m;i++) {
        int p=gi();
        if (isprime[p]==true) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
    return 0;
}
View Code

 

二十三、

KMP算法 字符串匹配

#include <bits/stdc++.h>
using namespace std;

int kmp[1000010];
char a[1000010],b[1000010];

int main()
{
    scanf("%s%s",a,b);
    int la=strlen(a),lb=strlen(b),k=0;
    for (int i=1;i<lb;i++) {
        while (k&&b[i]!=b[k]) k=kmp[k];
        kmp[i+1]=(b[i]==b[k])?++k:0;
    }
    k=0;
    for (int i=0;i<la;i++) {
        while (k&&a[i]!=b[k]) k=kmp[k];
        k+=(a[i]==b[k])?1:0;
        if (k==lb) printf("%d\n",i-lb+2);
    }
    for (int i=1;i<=lb;i++) printf("%d ",kmp[i]);
    return 0;
}
View Code

 

二十四、

tarjan缩点+最短路

#include <bits/stdc++.h>
using namespace std;

int last[100100],len=0,sccno[10010]={0},scc=0,n,m,u,v,w[10010]={0};
int dfn[10010]={0},low[10010]={0},dfscnt=0,wscc[10010]={0};
int f[100010]={0},t[100010]={0},ans=-2147483648,dis[10010]={0};
bool vis[10010];

stack <int> s;

struct edge {
    int next,to;
}e[100100];

int gi() {
    char c=getchar();bool f=0;int a=0;
    while (c<'0'||c>'9') {if (c=='-') f=1;c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0';c=getchar();}
    return f?-a:a;
 }

void add(int x,int y) {
    e[++len].to=y;
    e[len].next=last[x];
    last[x]=len;
 }

void init() {
    memset(last,-1,sizeof(last));
    n=gi();m=gi();
    for (int i=1;i<=n;i++) w[i]=gi();
    for (int i=1;i<=m;i++) {
        u=gi();v=gi();add(u,v);f[i]=u;t[i]=v;
     }
 }

int tarjan(int r) {
    s.push(r);
    dfn[r]=low[r]=++dfscnt;
    for (int i=last[r];i!=-1;i=e[i].next) {
        int y=e[i].to;
        if (!dfn[y]) {tarjan(y);low[r]=min(low[r],low[y]);}
        else if (!sccno[y]) low[r]=min(low[r],dfn[y]);
     }
    if (dfn[r]==low[r]) {
        scc++;
        while (1) {
            int x=s.top();sccno[x]=scc;wscc[scc]+=w[x];
            s.pop();if (x==r) break;
         }
     }
 }

void build() {
    len=0;
    memset(last,-1,sizeof(last));
    for (int i=1;i<=m;i++) {
        if (sccno[f[i]]!=sccno[t[i]]) add(sccno[f[i]],sccno[t[i]]);
     }
 }

int bfs(int x) {
    memset(dis,-1,sizeof(dis));
    memset(vis,false,sizeof(vis));
    dis[x]=wscc[x];
    queue <int> q;
    vis[x]=true;q.push(x);
    while (!q.empty()) {
        int u=q.front();q.pop();vis[u]=false;
        for (int i=last[u];i!=-1;i=e[i].next) {
            int v=e[i].to;
            if (dis[v]<dis[u]+wscc[v]) {
                dis[v]=dis[u]+wscc[v];
                if (!vis[v]) {vis[v]=true;q.push(v);}
             }
         }
     }
    for (int i=1;i<=scc;i++) ans=max(dis[i],ans);
 }

int main() {
    init();
    for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
    build();
    for (int i=1;i<=scc;i++) bfs(i);
    printf("%d\n",ans);
    return 0;
 }
View Code

 

二十五、

主席树

#include <bits/stdc++.h>
using namespace std;

const int N=300010;
struct value {int x,id;} a[N];
struct node {int l,r,sum;} ch[N*20];
int rank[N],root[N],cnt,n,m;
bool cmp(value x,value y) {return x.x<y.x;}

void init()
{
    cnt=1;
    root[0]=0;
    ch[0].l=ch[0].r=ch[0].sum;
}

void update(int num,int &rt,int l,int r)
{
    ch[cnt++]=ch[rt];
    rt=cnt-1;
    ++ch[rt].sum;
    if (l==r) return;
    int mid=l+r>>1;
    if (num<=mid) update(num,ch[rt].l,l,mid);
    else update(num,ch[rt].r,mid+1,r);
}

int query(int i,int j,int k,int l,int r)
{
    int d=ch[ch[j].l].sum-ch[ch[i].l].sum;
    if (l==r) return l;
    int mid=l+r>>1;
    if (k<=d) return query(ch[i].l,ch[j].l,k,l,mid);
    else return query(ch[i].r,ch[j].r,k-d,mid+1,r);
}

int main()
{
    cin>>n>>m;
    for (int i=1;i<=n;++i) {
        scanf("%d",&a[i].x);
        a[i].id=i;
    }
    sort(&a[1],&a[n+1],cmp);
    for (int i=1;i<=n;++i)
        rank[a[i].id]=i;
    init();
    for (int i=1;i<=n;++i) {
        root[i]=root[i-1];
        update(rank[i],root[i],1,n);
    }
    int l,r,k;
    for (int i=1;i<=m;++i) {
        scanf("%d%d%d",&l,&r,&k);
        printf("%d\n",a[query(root[l-1],root[r],k,1,n)].x);
    }
}
View Code

 

二十六、

字典树(trie树)

#include <bits/stdc++.h>
using namespace std;

char s[100];
const int N=2000010;
int tot=1,tree[N][26],n;

void insert(char *s,int rt)
{
    for (int i=0;s[i];i++) {
        int x=s[i]-'a';
        if (!tree[rt][x]) tree[rt][x]=++tot;
        rt=tree[rt][x];
    }
}

bool find(char *s,int rt)
{
    for (int i=0;s[i];i++) {
        int x=s[i]-'a';
        if (!tree[rt][x]) return 0;
        rt=tree[rt][x];
    }
    return 1;
}

int main()
{
    tot=0;int rt=1;
    scanf("%d",&n);
    for (int i=1;i<=n;i++) {scanf("%s",s);insert(s,rt);}
    scanf("%d",&n);
    for (int i=1;i<=n;i++) {
        scanf("%s",s);
        if (find(s,rt)) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
View Code

 

二十七、

快速排序

#include <bits/stdc++.h>
using namespace std;

int n,a[100010]={0};

inline void qsort(int l,int r)
{
    if(l==r) return;
    int i=l,j=r,mid=a[(l+r)>>1];
    do {
        while (a[i]<mid) i++;
        while (a[j]>mid) j--;
        if (i<=j)
        {
            swap(a[i],a[j]);
            i++;j--;
        }
    } while(i<=j);
    if (l<j) qsort(l,j);
    if (i<r) qsort(i,r);
}

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

 

二十八、

FFT快速傅里叶(假的 其实是python)

print(int(input())*int(input())) if input() else 0
View Code

 

二十九、

并查集

#include <bits/stdc++.h>
using namespace std;
#define INF 10000+5
#define INF2 200000+5

int n,m; 

struct Node{
    int rank;
    int father;
}node[INF+1];

int get_bigfather(int k)
{
    if(node[k].father==k)
        return k;
    else
    {
        node[k].father=get_bigfather(node[k].father);
        return node[k].father;
    }    
}

void merge(int u,int v)
{
    u=get_bigfather(u);
    v=get_bigfather(v);
    if(node[u].rank>node[v].rank) 
        node[v].father=u;
    else
    {
        node[u].father=v;
        if(node[u].rank==node[v].rank)
            node[v].rank++;
    }
}

int main() 
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        node[i].father=i;
    for(int i=1;i<=m;i++)
    {
        int temp,u,v;
        scanf("%d%d%d",&temp,&u,&v);
        if(temp==1)
            merge(u,v);
        else
        {
            if(get_bigfather(u)==get_bigfather(v))
                printf("Y\n");
            else
                printf("N\n");
        }
    }
    return 0; 
}
View Code

 

三十、

dfs版spfa判断负环

#include <bits/stdc++.h>
using namespace std;

int n,m,cnt,flag;
int head[10010];
bool vis[10010];
double dis[10010];

struct node{
int to,next;double v;
}edge[10010];

int read()
{
    int x=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*w;
}

void add(int x,int y,double v)
{
    cnt++;
    edge[cnt].to=y;
    edge[cnt].next=head[x];
    edge[cnt].v=v;
    head[x]=cnt;
}

void spfa(int k,double jian)
{
    vis[k]=1;
    int v;
    for(int i=head[k];i;i=edge[i].next)
    {
        v=edge[i].to;
        if(dis[v]>dis[k]+edge[i].v-jian)
        {
            if(vis[v])
            {
                flag=1;
                return;
            }
            dis[v]=dis[k]+edge[i].v-jian;
            spfa(v,jian);
            if(flag) return;
        }
    }
    vis[k]=0;
}

bool check(double mid)
{
    flag=0;
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
    {
        spfa(i,mid);
        if(flag) return 1;
    }
    return 0;
}

int main()
{
    int x,y;
    double z;
    n=read();m=read();
    for(int i=1;i<=m;i++)
    {
        x=read();y=read();
        scanf("%lf",&z);
        add(x,y,z);
    }
    double l=-10000000,r=10000000,mid;
    while(r-l>1e-10)
    {
        mid=(l+r)/2;
        if(check(mid))
        {
            r=mid;
        }
        else
        {
            l=mid;
        }
    }
    printf("%.8lf",mid);
    return 0;
}
View Code

 

三十一、

BF算法(暴风算法)

#include <bits/stdc++.h>
using namespace std;

int index_bf(char *s,char *t,int pos);  
int index_bf_self(char *s,char *t,int index);  

int main()  
{  
    char s[]="6he3wor";
    char t[]="3wor";  
    int m=index_bf(s,t,2);
    printf("index_bf:%d\n",m);  
    m=index_bf_self(s,t,2);
    printf("index_bf_self:%d\n",m);  
    exit(0);  
}  

int index_bf(char *s,char *t,int pos)  
{  
    int i,j;  
    if(pos>=1 && pos <=s[0]-'0')  
    {  
        i=pos;  
        j=1;  
        while(i<=s[0]-'0'&&j<=t[0]-'0')  
        {  
            if(s[i]==t[j])  
            {  
                i++;  
                j++;  
            }  
            else   
            {  
                j=1;  
                i=i-j+2;  
            }  
            if(j>t[0]-'0')  
            {  
                return i-t[0]+'0';  
            }  
        }  
        return -1;  
    }  
    else   
    {  
        return -1;  
    }  
}  

int index_bf_self(char *s,char *t,int index)  
{  
    int i=index,j=0;  
    while(s[i]!='\0')  
    {  
        while(*(t+j)!='\0' && *(s+i+j)!='\0')  
        {  
            if(*(t+j)!=*(s+i+j))  
                break;  
            j++;  
        }  
        if(*(t+j)=='\0')  
        {  
            return i;  
        }  
        i++;  
        j=0;  
    }  
    return -1;  
}
View Code

 

三十二、

高斯消元法Gauss

//Guss
#include <bits/stdc++.h>
using namespace std;

int n;
double f[105][105];
const double eps=1e-8;

int main()
{
    scanf("%d",&n);
    for (int i=0;i<n;i++)//读入系数和值
    for (int j=0;j<=n;j++) scanf("%lf",&f[i][j]);
    for (int i=0;i<n;i++) {
        int ch=i;
        for (int j=i;j<n;j++)//选择绝对值最大的减少误差
        if (fabs(f[j][i]-f[ch][i])<=eps) ch=j;
        for (int j=0;j<=n;j++) swap(f[i][j],f[ch][j]);//交换
        if (fabs(f[i][i])<=eps) {//无解情况
            printf("No Solution\n");
            return 0;//如果当前位置为零 则无解 0x=A
        }
        for (int j=i+1;j<=n;j++) f[i][j]/=f[i][i];//系数化1
        //自己那位不必要除 无影响
        for (int j=0;j<n;j++)
        if (i!=j)
        for (int k=i+1;k<=n;k++) f[j][k]-=f[j][i]*f[i][k];
        //加减法去掉系数值
    }
    for (int i=0;i<n;i++) printf("%.2lf\n",f[i][n]);//输出
    return 0;
}
View Code

 

三十三、

扫描线(洛谷 ‘楼房’)

#include <bits/stdc++.h>
#define N 100010
using namespace std;

int n,cnt,num;
multiset <int> s;

struct thing {int h,l,r;}a[N];

struct lines {int up,x,k;}l[N*2];

struct anspr {int ax,ay;}ans[N*4];

bool cmp(lines i,lines j)
{
    if (i.x!=j.x) return i.x<j.x;
    if (i.k!=j.k) return i.k<j.k;
    if (i.k==1) return i.up>j.up;
    if (i.k==2) return i.up<j.up;
}

int main()
{
    cin>>n;
    for (int i=1;i<=n;i++) {
        int q,w,e;
        scanf("%d%d%d",&q,&w,&e);
        a[i].h=q,a[i].l=w,a[i].r=e;
        l[++cnt].up=q;l[cnt].x=w,l[cnt].k=1;
        l[++cnt].up=q;l[cnt].x=e,l[cnt].k=2;
    }
    sort(l+1,l+1+cnt,cmp);
    s.insert(0);
    for (int i=1;i<=cnt;i++) {
        int mx=*s.rbegin();
        if (l[i].k==1) {
            if (l[i].up<=mx) s.insert(l[i].up);
            else {
                ans[++num].ax=l[i].x;ans[num].ay=mx;
                ans[++num].ax=l[i].x;ans[num].ay=l[i].up;
                s.insert(l[i].up);
            }
        }
        if (l[i].k==2) {
            if (l[i].up==mx&&s.count(mx)==1) {
                s.erase(mx);
                ans[++num].ax=l[i].x;ans[num].ay=l[i].up;
                ans[++num].ax=l[i].x;ans[num].ay=*s.rbegin();
            }
            else s.erase(s.find(l[i].up));
        }
    }
    cout<<num<<endl;
    for (int i=1;i<=num;i++)
    printf("%d %d\n",ans[i].ax,ans[i].ay);
    return 0;
}
View Code

 

三十四、

Meeting-in-the-Middle

#include <bits/stdc++.h>
using namespace std;

const int maxn=24;
map <int,int> table;

int bitcount(int x) {
    return x==0?0:bitcount(x/2)+(x&1);
}//这个函数用来计算这个数在二进制下有多少个1

int main()
{
    int n,A[maxn];
    char s[1000];
    while (scanf("%d",&n)==1&&n) {//读入多组数据
        for (int i=0;i<n;i++) {
            scanf("%s",s);//输入字符串
            A[i]=0;
            for (int j=0;s[j]!='\0';j++)
            A[i]^=(1<<(s[j]-'A'));//计算每一串的<=26位二进制值
        }
        table.clear();//清空table映射
        int n1=n/2,n2=n-n1;//将待测数据分成两部分
        
        //接下来循环计算2^(n/2)个属于前半部分的子集
        for (int i=0;i<(1<<n1);i++) {
            int x=0;
            for (int j=0;j<n1;j++)
            if (i&(1<<j)) x^=A[j];
            if (!table.count(x)||bitcount(table[x])<bitcount(i))
            table[x]=i;
        }//取每个计算结果中的最大值

        //最后处理后半部分
        int ans=0;
        for (int i=0;i<(1<<n2);i++) {
            int x=0;
            for (int j=0;j<n2;j++)
            if (i&(1<<j)) x^=A[n1+j];
            if (table.count(x)&&bitcount(ans)<bitcount(table[x])+bitcount(i))
            ans=(i<<n1)^table[x];
        }//每次计算前查找映射中是否出现过
        printf("%d\n",bitcount(ans));
        for (int i=0;i<n;i++)
        if (ans&(1<<i)) printf("%d ",i+1);
        printf("\n");//输出部分
    }
    return 0;
}
View Code

 

三十五、

左偏树(可并堆)

#include <bits/stdc++.h>
using namespace std;

const int N=101000;
struct leftist{
    int l,r,k,f,d;
}h[N];
int n,m;

int merge(int u,int v)
{
    if (!u||!v)
    return u+v;
    if (h[u].k>h[v].k||(h[u].k==h[v].k&&u>v))
    swap(u,v);
    int &ul=h[u].l,&ur=h[u].r;
    ur=merge(ur,v);
    h[ur].f=u;
    if (h[ul].d<h[ur].d)
    swap(ul,ur);
    h[u].d=h[ur].d+1;
    return u;
}

void erase(int u)
{
    int ul=h[u].l,ur=h[u].r;
    h[u].k=-1;
    h[ul].f=0;
    h[ur].f=0;
    merge(ul,ur);
}

int find(int x)
{
    return h[x].f?find(h[x].f):x;
}

int main()
{
    cin>>n>>m;
    h[0].d=-1;
    for (int i=1;i<=n;i++)
    scanf("%d",&h[i].k);
    for (int i=1;i<=m;i++) {
        int opt,x,y;
        scanf("%d%d",&opt,&x);
        if (opt==1) {
            scanf("%d",&y);
            if (h[x].k!=-1 && h[y].k!=-1) {
                int p=find(x),q=find(y);
                if (p!=q)
                merge(p,q);
            }
        }
        else if (opt==2) {
            if (h[x].k==-1)
            printf("-1\n");
            else {
                int p=find(x);
                printf("%d\n",h[p].k);
                erase(p);
            }
        }
    }
    return 0;
}
View Code

 

三十六

分块(小b的询问)

// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;

const int N=50010,S=250;
int n,m,q,a[N],s[S][S];
int f[S][N],block,num;
int belong[N],l[S],r[S],tmp[N];

void build()
{
    block=sqrt(n);
    num=n/block;
    if (n%block) num++;
    for (int i=1;i<=num;i++)
    l[i]=(i-1)*block+1,r[i]=i*block;
    r[num]=n;
    for (int i=1;i<=n;i++)
    belong[i]=(i-1)/block+1;
    for (int i=1;i<=num;i++) {
        for (int j=1;j<=n;j++)
        f[i][a[j]]=f[i-1][a[j]];
        for (int j=l[i];j<=r[i];j++)
        f[i][a[j]]++;
    }
    for (int i=1;i<=num;i++)
    for (int j=i;j<=num;j++) {
        s[i][j]=s[i][j-1];
        for (int k=l[j];k<=r[j];k++) {
            int p=f[j-1][a[k]]-f[i-1][a[k]];
            s[i][j]+=2*(p+tmp[a[k]])+1;
            tmp[a[k]]++;
        }
        for (int k=l[j];k<=r[j];k++)
        tmp[a[k]]=0;
    }
}

long long ask(int ls,int rs)
{
    long long ans=0;
    if (belong[ls]==belong[rs]) {
        for (int i=ls;i<=rs;i++) {
            ans+=2*tmp[a[i]]+1;
            tmp[a[i]]++;
        }
        for (int i=ls;i<=rs;i++) tmp[a[i]]=0;
        return ans;
    }
    for (int i=ls;i<=r[belong[ls]];i++) {
        int p=f[belong[rs]-1][a[i]]-f[belong[ls]][a[i]];
        ans+=2*(p+tmp[a[i]])+1;
        tmp[a[i]]++;
    }
    for (int i=l[belong[rs]];i<=rs;i++) {
        int p=f[belong[rs]-1][a[i]]-f[belong[ls]][a[i]];
        ans+=2*(p+tmp[a[i]])+1;
        tmp[a[i]]++;
    }
    for (int i=ls;i<=r[belong[ls]];i++) tmp[a[i]]=0;
    for (int i=l[belong[rs]];i<=rs;i++) tmp[a[i]]=0;
    if (belong[ls]+1==belong[rs]) return ans;
    return ans+s[belong[ls]+1][belong[rs]-1];
}

int main()
{
    ios::sync_with_stdio(0);
    cin>>n>>m>>q;
    for (int i=1;i<=n;i++)
    cin>>a[i];
    build();
    while (m--) {
        int ls,rs;
        cin>>ls>>rs;
        cout<<ask(ls,rs)<<endl;
    }
    return 0;
}
View Code

 

三十七

莫队(小z的袜子)

#include <bits/stdc++.h>
using namespace std;

int id[50005];
const int N=50005;
struct Mo {
    int x,y,num;
    bool operator < (const Mo &a) const {
        if (id[x]==id[a.x])
        return (id[x]&1)?y<a.y:y>a.y;
        return x<a.x;
    }
}q[N];
int n,m,c[N],len,l=1,r;
unsigned int cnt[N],ans[N][2],g,k,now;

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

int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for (int i=1;i<=n;i++) cin>>c[i];
    len=sqrt(n);
    for (int i=1;i<=m;i++)
    cin>>q[i].x>>q[i].y,q[i].num=i,id[i]=i/len+1;
    sort(q+1,q+1+m);
    for (int i=1;i<=m;i++) {
        if (q[i].x==q[i].y) continue;
        while (l<q[i].x) {
            --cnt[c[l]];now-=cnt[c[l]];++l;
        }
        while (l>q[i].x) {
            --l;now+=cnt[c[l]];++cnt[c[l]];
        }
        while (r<q[i].y) {
            ++r;now+=cnt[c[r]];++cnt[c[r]];
        }
        while (r>q[i].y) {
            --cnt[c[r]];now-=cnt[c[r]];--r;
        }
        if (!now) continue;
        k=(unsigned int)(r-l+1)*(r-l);
        g=gcd(now<<1,k);
        ans[q[i].num][0]=(now<<1)/g;
        ans[q[i].num][1]=k/g;
    }
    for (int i=1;i<=m;i++)
    if (!ans[i][0]) cout<<"0/1"<<endl;
    else cout<<ans[i][0]<<"/"<<ans[i][1]<<endl;
    return 0;
}
View Code

 

三十八

tarjan求割点

#include <bits/stdc++.h>
using namespace std;

const int N=100010;
bool cut[N];
int dfn[N],low[N],dfscnt;
int n,m,s[N*2][2],o[N],cnt,fa[N],size[N];

void add(int x,int y)
{
    s[++cnt][0]=y;s[cnt][1]=o[x];o[x]=cnt;
}

void tarjan(int x,int fa)
{
    int i=o[x];dfn[x]=low[x]=++dfscnt;
    while (i!=-1) {
        if (!dfn[s[i][0]]) {
            size[x]++;tarjan(s[i][0],x);
            if (low[s[i][0]]>=dfn[x]) cut[x]=1;
            else low[x]=min(low[x],low[s[i][0]]);
        }
        else if (s[i][0]!=fa)
        low[x]=min(low[x],dfn[s[i][0]]);
        i=s[i][1];
    }
    if (size[x]==1&&!fa) cut[x]=0;
}

int main()
{
    int ans=0;
    ios::sync_with_stdio(false);
    cin>>n>>m;int x,y;
    memset(o,-1,sizeof(o));
    for (int i=1;i<=m;i++) {
        cin>>x>>y;add(x,y);add(y,x);
    }
    for (int i=1;i<=n;i++)
    if (!dfn[i]) tarjan(i,0);
    for (int i=1;i<=n;i++) if (cut[i]) ans++;
    cout<<ans<<endl;
    for (int i=1;i<=n;i++)
    if (cut[i]) cout<<i<<' ';cout<<endl;
    return 0;
}
View Code

 

三十九、

凸包(扫描法)

#include <bits/stdc++.h>
using namespace std;

const int N=10010;
struct node {
    double x,y;
}p[N],s[N];
int top,n;

bool cmp(node a,node b)
{
    double A=atan2(a.y-p[1].y,a.x-p[1].x);
    double B=atan2(b.y-p[1].y,b.x-p[1].x);
    return A==B?a.x<b.x:A<B;
}

double cross(node a,node b,node c)
{
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}

double dis(node a,node b)
{
    return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+1.0*(a.y-b.y)*(a.y-b.y));
}

int main()
{
    cin>>n;
    for (int i=1;i<=n;++i) scanf("%lf%lf",&p[i].x,&p[i].y);
    p[0].x=p[0].y=999999999;
    int k;
    for (int i=1;i<=n;++i)
    if (p[0].y>p[i].y||(p[0].y==p[i].y&&p[0].x>p[i].x))
    p[0]=p[i],k=i;
    swap(p[k],p[1]);sort(&p[2],&p[n+1],cmp);
    s[0]=p[1],s[1]=p[2],top=1;
    for (int i=3;i<=n;) {
        if (top&&cross(s[top-1],p[i],s[top])>=0)
        --top;
        else s[++top]=p[i++];
    }
    double ans=0;
    if (top==0) ans=0;
    else if (top==1) ans=dis(s[0],s[1]);
    else {
        s[++top]=s[0];
        for (int i=0;i<top;++i) ans+=dis(s[i],s[i+1]);
    }
    printf("%.2lf\n",ans);
    return 0;
}
View Code

 

四十、

2-sat(tarjan)

#include <bits/stdc++.h>
using namespace std;

const int N=2000010;
bool flag=1;
int n,m,scc,dfscnt;
int s[N<<1][2],o[N];
int low[N],dfn[N],sccno[N];
stack <int> sta;

void read(int &aa)
{
    aa=0;char c=getchar();
    while (c>'9'||c<'0') c=getchar();
    while (c>='0'&&c<='9')
        aa=(aa<<3)+(aa<<1)+(c^48),c=getchar();
}

void add(int x,int y)
{
    s[++o[0]][0]=y,s[o[0]][1]=o[x],o[x]=o[0];
}

void tarjan(int x)
{
    low[x]=dfn[x]=++dfscnt;
    sta.push(x);
    for (int i=o[x];i;i=s[i][1]) {
        int y=s[i][0];
        if (!dfn[y])
            tarjan(y),low[x]=min(low[x],low[y]);
        else if (!sccno[y])
            low[x]=min(low[x],dfn[y]);
    }
    if (dfn[x]==low[x]) {
        ++scc;
        while (1) {
            int y=sta.top();
            sta.pop();
            sccno[y]=scc;
            if (x==y) break;
        }
    }
}

int main()
{
    read(n),read(m);
    int a,b,aval,bval,nota,notb;
    for (int i=1;i<=m;++i) {
        read(a),read(aval),read(b),read(bval);
        nota=aval^1,notb=bval^1;
        add(a+nota*n,b+bval*n);
        add(b+notb*n,a+aval*n);
    }
    for (int i=1;i<=(n<<1);++i)
        if (!dfn[i]) tarjan(i);
    for (int i=1;i<=m;++i)
        if (sccno[i]==sccno[i+n]) {flag=0;break;}
    if (flag) {
        puts("POSSIBLE");
        for (int i=1;i<=n;++i)
            printf("%d ",sccno[i]>sccno[i+n]);
    }
    else puts("IMPOSSIBLE");
    return 0;
}
View Code

 

未完待续。。。

推荐阅读