模板

图论:

最小生成树

kruskal

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=5000+50;
const int maxm=200000+50;

int n,m,fat[maxn];

struct node{int x,y,z;}a[maxm];
int cmp(const node &a,const node &b){return a.z<b.z;}

int father(int x){
    if(x!=fat[x]) fat[x]=father(fat[x]);
    return fat[x];
}

void kruskal(){
    int k=0,ans=0;
    for(int i=1;i<=m;i++){
        int fa=father(a[i].x);
        int fb=father(a[i].y);
        if(fa!=fb){
            fat[fa]=fb;
            k++;
            ans+=a[i].z;
        }
        if(k==n-1) break;
    }
    if(k==n-1) printf("%d",ans);
    else printf("orz");
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    read(n),read(m);
    for(int i=1;i<=n;i++) fat[i]=i;
    for(int i=1;i<=m;i++) read(a[i].x),read(a[i].y),read(a[i].z);
    sort(a+1,a+1+m,cmp);
    kruskal();
    return 0;
}
View Code

 

kruskal重构树

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=200000+50;

int n,m,k,aa,bb,fat[maxn],cnt;
int fir[maxn],to[maxn],nex[maxn],ecnt;
int son[maxn],dep[maxn],sz[maxn],fa[maxn],top[maxn],val[maxn];

struct node{int x,y,z;}a[maxn];

void add_edge(int u,int v){
    nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;
}

int cmp(const node &a,const node &b){
    return a.z<b.z;
}

int father(int x){
    if(x!=fat[x]) fat[x]=father(fat[x]);
    return fat[x];
}

void dfs1(int x,int f,int deep){
    dep[x]=deep;
    fa[x]=f;
    sz[x]=1;
    int maxson=-1;
    for(int e=fir[x];e;e=nex[e]){
        int v=to[e];
        if(v==f) continue;
        dfs1(v,x,deep+1);
        sz[x]+=sz[v];
        if(sz[v]>maxson) maxson=sz[v],son[x]=v;
    }
}

void dfs2(int x,int topf){
    top[x]=topf;
    if(!son[x]) return ;
    dfs2(son[x],topf);
    for(int e=fir[x];e;e=nex[e]){
        int v=to[e];
        if(v==fa[x]||v==son[x]) continue;
        dfs2(v,v);
    }
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

void kruskal(){
    sort(a+1,a+1+m,cmp);
    for(int i=1;i<=m;i++){
        if(father(a[i].x)!=father(a[i].y)){
            int fa=father(a[i].x),fb=father(a[i].y);
            val[++cnt]=a[i].z;
            fat[cnt]=fat[fa]=fat[fb]=cnt;
            add_edge(fa,cnt);
            add_edge(cnt,fa);
            add_edge(fb,cnt);
            add_edge(cnt,fb);
        }
    }
}

int lca(int x,int y){
    int f1=top[x],f2=top[y];
    while(f1!=f2){
        if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
        x=fa[f1];f1=top[x];
    }
    return dep[x]<dep[y]?x:y;
}

int main(){
    read(n),read(m),read(k);cnt=n;
    for(int i=1;i<=m;i++)
    read(a[i].x),read(a[i].y),read(a[i].z);
    for(int i=1;i<=n;i++) fat[i]=i;
    kruskal();
    dfs1(cnt,0,1);dfs2(cnt,cnt);
    while(k--){
        read(aa),read(bb);
        cout<<val[lca(aa,bb)]<<endl;
    }
    return 0;
}
View Code

 

最短路

floyed

void floyd(){
    memset(dis,63,sizeof(dis));
    for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
View Code

 

spfa

#include<queue>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=10000+50;
const int maxm=500000+50;
const int inf=2147483647;

int n,m,s,d[maxn];
int fir[maxn],nex[maxm],to[maxm],wi[maxm],ecnt;
bool vis[maxn];

queue<int> q;

void add(int u,int v,int w){
    nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;wi[ecnt]=w;
}

void spfa(int x){
    memset(vis,false,sizeof(vis));vis[x]=true;
    for(int i=1;i<=n;i++) d[i]=inf;d[x]=0;
    q.push(x);
    while(!q.empty()){
        int u=q.front();q.pop();
        vis[u]=false;
        for(int e=fir[u];e;e=nex[e]){
            int v=to[e];
            if(d[v]>d[u]+wi[e]){
                d[v]=d[u]+wi[e];
                if(!vis[v]){
                    q.push(v);
                    vis[v]=true;
                }
            }
        }
    }
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    read(n),read(m),read(s);
    for(int i=1;i<=m;i++){
        int x,y,z;
        read(x),read(y),read(z);
        add(x,y,z);
    }
    spfa(s);
    for(int i=1;i<=n;i++) printf("%d ",d[i]);
    return 0;
}
View Code

 

dijsktra

#include<queue>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=100000+50;
const int maxm=200000+50;

int n,m,s,d[maxn];
int fir[maxn],nex[maxm],to[maxm],wi[maxm],ecnt;
bool vis[maxn];

priority_queue<pair<ll,int> > q;

void add(int u,int v,int w){
    nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;wi[ecnt]=w;
}

void dijsktra(int x){
    memset(vis,false,sizeof(vis));
    memset(d,127,sizeof(d));d[x]=0;
    q.push(make_pair(0,x));
    while(!q.empty()){
        int u=q.top().second;q.pop();
        if(vis[u]) continue;
        vis[u]=true;
        for(int e=fir[u];e;e=nex[e]){
            int v=to[e];
            if(d[v]>d[u]+wi[e]){
                d[v]=d[u]+wi[e];
                q.push(make_pair(-d[v],v));
            }
        }
    }
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    read(n),read(m),read(s);
    for(int i=1;i<=m;i++){
        int x,y,z;
        read(x),read(y),read(z);
        add(x,y,z);
    }
    dijsktra(s);
    for(int i=1;i<=n;i++) printf("%d ",d[i]);
    return 0;
}
View Code

 

tarjan

强连通分量

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=10000+50;
const int maxm=50000+50;

int fir[maxn],nex[maxm],to[maxm],ecnt;
int col[maxn],dfn[maxm],low[maxm],stack[maxm],vis[maxn],cnt[maxn];
int n,m,t,deep,sum,ans,x,y;

void add_edge(int u,int v){
    nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int tarjan(int u){
    dfn[u]=++deep;
    low[u]=deep;
    vis[u]=1;
    stack[++t]=u;
    for(int e=fir[u];e;e=nex[e]){
        int v=to[e];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else{
            if(vis[v]) low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u]){
        col[u]=++sum;
        vis[u]=0;
        while(stack[t]!=u){
            col[stack[t]]=sum;
            vis[stack[t--]]=0;
        }
        t--;
    }
}

int main(){
    read(n),read(m);
    for(int i=1;i<=m;i++){
        read(x),read(y);
        add_edge(x,y);
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i]) tarjan(i);
    }
    for(int i=1;i<=n;i++) cnt[col[i]]++;
    for(int i=1;i<=sum;i++){
        if(cnt[i]>1) ans++;
    }
    cout<<ans<<endl;
    return 0;
}
View Code

 

最近公共祖先

倍增

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=500000+5;
const int maxm=500000*2+5;

int n,m,s,x,y,a,b;
int fir[maxn],to[maxm],nex[maxm],ecnt;
int anc[maxn][22],lg[maxn],dep[maxn];

void add_edge(int u,int v){
    nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

void dfs(int u,int fa){
    dep[u]=dep[fa]+1;anc[u][0]=fa;
    for(int i=1;(1<<i)<=dep[u];i++)
    anc[u][i]=anc[anc[u][i-1]][i-1];
    for(int e=fir[u];e;e=nex[e])
    if(to[e]!=fa) dfs(to[e],u);
}

int lca(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    while(dep[x]>dep[y]) x=anc[x][lg[dep[x]-dep[y]]-1];
    if(x==y) return x;
    for(int k=lg[dep[x]];k>=0;k--)
    if(anc[x][k]!=anc[y][k]) x=anc[x][k],y=anc[y][k];
    return anc[x][0];
}

int main(){
    read(n),read(m),read(s);
    for(int i=1;i<n;i++){
        read(x),read(y);
        add_edge(x,y);add_edge(y,x);
    }
    dfs(s,0);
    for(int i=1;i<=n;i++)
    lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    for(int i=1;i<=m;i++){
        read(a),read(b);
        printf("%d\n",lca(a,b));
    }
    return 0;
}
View Code

 

树剖

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=500000+50;
const int maxm=500000*2+50;

int n,m,s;
int fir[maxn],nex[maxm],to[maxm],ecnt;
int fa[maxn],top[maxm],sz[maxn],son[maxn],dep[maxn];

void add(int u,int v){
    nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;
}

void dfs1(int x,int f,int deep){
    fa[x]=f;
    dep[x]=deep;
    sz[x]=1;
    for(int e=fir[x];e;e=nex[e]){
        int v=to[e];
        if(v==f) continue;
        dfs1(v,x,deep+1);
        sz[x]+=sz[v];
        if(sz[v]>sz[son[x]]) son[x]=v;
    }
}

void dfs2(int x,int topf){
    top[x]=topf;
    if(!son[x]) return ;
    dfs2(son[x],topf);
    for(int e=fir[x];e;e=nex[e]){
        int v=to[e];
        if(v==fa[x]||v==son[x]) continue;
        dfs2(v,v);
    }
}

int lca(int x,int y){
    int f1=top[x],f2=top[y];
    while(f1!=f2){
        if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
        x=fa[f1];f1=top[x];
    }
    return dep[x]<dep[y]?x:y;
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    read(n),read(m),read(s);
    for(int i=1;i<n;i++){
        int x,y;
        read(x),read(y);
        add(x,y);add(y,x);
    }
    dfs1(s,0,1);
    dfs2(s,s);
    while(m--){
        int x,y;
        read(x),read(y);
        printf("%d\n",lca(x,y));
    }
    return 0;
}
View Code

 

树链剖分

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=1e5+50;
const int maxm=2e5+50;

int n,m,r,p,val[maxn],cnt;
int fir[maxn],nex[maxm],to[maxm],ecnt;
int son[maxn],dep[maxn],sz[maxn],top[maxn],fa[maxn],id[maxn],wt[maxn];

struct SegmentTree{int l,r;ll v,add;}st[maxn<<2];

void add(int u,int v){
    nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;
}

void dfs1(int x,int f,int deep){
    fa[x]=f;dep[x]=deep;
    sz[x]=1;
    for(int e=fir[x];e;e=nex[e]){
        int v=to[e];
        if(v==f) continue;
        dfs1(v,x,deep+1);
        sz[x]+=sz[v];
        if(sz[v]>sz[son[x]]) son[x]=v;
    }
}

void dfs2(int x,int topf){
    top[x]=topf;
    id[x]=++cnt;
    wt[cnt]=val[x];
    if(!son[x]) return ;
    dfs2(son[x],topf);
    for(int e=fir[x];e;e=nex[e]){
        int v=to[e];
        if(v==fa[x]||v==son[x]) continue;
        dfs2(v,v);
    }
}

void pushup(int root){
    st[root].v=(st[root<<1].v+st[root<<1|1].v)%p;
}

void build(int root,int l,int r){
    st[root].l=l;st[root].r=r;
    if(l==r) st[root].v=wt[l];
    else{
        int m=l+r>>1;
        build(root<<1,l,m);build(root<<1|1,m+1,r);
        pushup(root);
    }
}

void pushdown(int root){
    st[root<<1].v=(st[root<<1].v+st[root].add*(st[root<<1].r-st[root<<1].l+1))%p;
    st[root<<1|1].v=(st[root<<1|1].v+st[root].add*(st[root<<1|1].r-st[root<<1|1].l+1))%p;
    st[root<<1].add=(st[root<<1].add+st[root].add)%p;
    st[root<<1|1].add=(st[root<<1|1].add+st[root].add)%p;
    st[root].add=0;
}

void change(int root,int l,int r,ll val){
    if(st[root].l>r||st[root].r<l) return ;
    if(st[root].l>=l&&st[root].r<=r){
        st[root].v=(st[root].v+val*(st[root].r-st[root].l+1))%p;
        st[root].add=(st[root].add+val)%p;
    }
    else{
        pushdown(root);
        change(root<<1,l,r,val);change(root<<1|1,l,r,val);
        pushup(root);
    }
}

ll query(int root,int l,int r){
    if(st[root].l>r||st[root].r<l) return 0;
    if(st[root].l>=l&&st[root].r<=r) return st[root].v;
    pushdown(root);
    return (query(root<<1,l,r)+query(root<<1|1,l,r))%p; 
}

void Chg(int x,int y,ll val){
    int f1=top[x],f2=top[y];
    while(f1!=f2){
        if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
        change(1,id[f1],id[x],val);
        x=fa[f1];f1=top[x];
    }
    if(dep[x]>dep[y]) swap(x,y);
    change(1,id[x],id[y],val);
}

ll Qry(int x,int y){
    int f1=top[x],f2=top[y];ll ans=0;
    while(f1!=f2){
        if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
        ans=(ans+query(1,id[f1],id[x]));
        x=fa[f1];f1=top[x];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans=(ans+query(1,id[x],id[y]))%p;
    return ans;
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    read(n),read(m),read(r),read(p);
    for(int i=1;i<=n;i++) read(val[i]);
    for(int i=1;i<n;i++){
        int x,y;
        read(x),read(y);
        add(x,y);add(y,x);
    }
    dfs1(r,0,1);dfs2(r,r);build(1,1,n);
    while(m--){
        int op,x,y,z;
        read(op);
        if(op==1){
            read(x),read(y),read(z);
            Chg(x,y,z);
        }
        else if(op==2){
            read(x),read(y);
            printf("%lld\n",Qry(x,y));
        }
        else if(op==3){
            read(x),read(y);
            change(1,id[x],id[x]+sz[x]-1,y);
        }
        else{
            read(x);
            printf("%lld\n",query(1,id[x],id[x]+sz[x]-1));
        }
    }
    return 0;
}
View Code

 

 


 

数据结构:

树状数组

单点加,区间和

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=500000+5;

int a[maxn],c[maxn],n,m,op,x,y,k;

template<typename T>void read(T& aa) {
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

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

int query(int x){
    int ans=0;
    while(x){
        ans+=c[x];x-=lowbit(x);
    }
    return ans;
}

void update(int x,int y){
    while(x<=n){
        c[x]+=y;x+=lowbit(x);
    }
}

int main(){
    read(n),read(m);
    for(int i=1;i<=n;i++){
        read(a[i]);
        update(i,a[i]);
    }
    while(m--){
        read(op);
        if(op==1){
            read(x),read(y);
            update(x,y);
        }
        else {
            read(x),read(y);
            printf("%d\n",query(y)-query(x-1));
        }
    }
    return 0;
}
View Code

 

区间加,单点查询

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=500000+5;

int a[maxn],c[maxn],n,m,x,y,k,op,now;

template<typename T>void read(T& aa) {
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

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

int query(int x){
    int ans=0;
    while(x){
        ans+=c[x];x-=lowbit(x);
    }
    return ans;
}

void update(int x,int y){
    while(x<=n){
        c[x]+=y;x+=lowbit(x);
    }
}

int main(){
    read(n),read(m);
    for(int i=1;i<=n;i++){
        read(a[i]);
        update(i,a[i]-now);
        now=a[i];
    }
    while(m--){
        read(op);
        if(op==1){
            read(x),read(y),read(k);
            update(x,k);update(y+1,-k);
        }
        else{
            read(x);
            printf("%d\n",query(x));
        }
    }
    return 0;
}
View Code

 

线段树

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=100000+50;

int n,m,p;ll a[maxn];

struct SegmentTree{int l,r;ll v,add,mul;}st[maxn<<2];

void pushup(int root){
    st[root].v=(st[root<<1].v+st[root<<1|1].v)%p;
}

void build(int root,int l,int r){
    st[root].l=l;st[root].r=r;st[root].mul=1;
    if(l==r) st[root].v=a[l];
    else{
        int m=l+r>>1;
        build(root<<1,l,m);build(root<<1|1,m+1,r);
        pushup(root);
    }
}

void pushdown(int root){
    st[root<<1].v=(st[root<<1].v*st[root].mul+st[root].add*(st[root<<1].r-st[root].l+1))%p;
    st[root<<1|1].v=(st[root<<1|1].v*st[root].mul+st[root].add*(st[root<<1|1].r-st[root<<1|1].l+1))%p;
    st[root<<1].mul=st[root<<1].mul*st[root].mul%p;
    st[root<<1|1].mul=st[root<<1|1].mul*st[root].mul%p;
    st[root<<1].add=(st[root<<1].add*st[root].mul+st[root].add)%p;
    st[root<<1|1].add=(st[root<<1|1].add*st[root].mul+st[root].add)%p;
    st[root].add=0;st[root].mul=1;
}

void u1(int root,int l,int r,ll val){
    if(st[root].l>r||st[root].r<l) return ;
    if(st[root].l>=l&&st[root].r<=r){
        st[root].v=st[root].v*val%p;
        st[root].add=st[root].add*val%p;
        st[root].mul=st[root].mul*val%p;
    }
    else{
        pushdown(root);
        u1(root<<1,l,r,val);u1(root<<1|1,l,r,val);
        pushup(root);
    }
}

void u2(int root,int l,int r,ll val){
    if(st[root].l>r||st[root].r<l) return ;
    if(st[root].l>=l&&st[root].r<=r){
        st[root].v=(st[root].v+val*(st[root].r-st[root].l+1))%p;
        st[root].add=(st[root].add+val)%p;
    }
    else{
        pushdown(root);
        u2(root<<1,l,r,val);u2(root<<1|1,l,r,val);
        pushup(root);
    }
}

ll query(int root,int l,int r){
    if(st[root].l>r||st[root].r<l) return 0;
    if(st[root].l>=l&&st[root].r<=r) return st[root].v;
    pushdown(root);
    return (query(root<<1,l,r)+query(root<<1|1,l,r))%p;
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    read(n),read(m),read(p);
    for(int i=1;i<=n;i++) read(a[i]);
    build(1,1,n);
    while(m--){
        int op,x,y;ll k;
        read(op),read(x),read(y);
        if(op==1){
            read(k);
            u1(1,x,y,k);
        }
        else if(op==2){
            read(k);
            u2(1,x,y,k);
        }
        else printf("%lld\n",query(1,x,y));
    }
    return 0;
}
View Code

 

权值线段树

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define ull unsigned long long
#define maxx 2139062143
#define maxint 2147483647
using namespace std;

const int maxn=100000+5;

int T[4*maxn];
int n,opt[maxn],a[maxn],ma[maxn],e,x;

struct Data{
    int v,p;
}t[maxn];

bool cmp(const Data &a,const Data &b){
    return a.v<b.v;
}

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

void update(int root,int p,int v,int l,int r){//插入p时v==1,删除p时v==-1 
    T[root]+=v;
    if(l==r) return ;
    int m=(l+r>>1);
    if(p<=m) update(root*2,p,v,l,m);
    else update(root*2+1,p,v,m+1,r);
}

int kth(int root,int k,int l,int r){
    if(l==r) return l;
    int m=(l+r>>1);
    if(T[root*2]>=k) return kth(root*2,k,l,m);
    return kth(root*2+1,k-T[root*2],m+1,r);
}

int rank(int root,int p,int l,int r){
    if(r<p) return T[root];
    int m=(l+r>>1),res=0;
    res+=rank(root*2,p,l,m);
    if(m<p-1) res+=rank(root*2+1,p,m+1,r);
    return res;
}

int findp(int root,int l,int r){
    if(l==r) return l;
    int m=(l+r>>1);
    if(T[root*2+1]) return findp(root*2+1,m+1,r);
    return findp(root*2,l,m);
}

int pre(int root,int p,int l,int r){
    if(r<p){
        if(T[root]) return findp(root,l,r);
        return 0;
    }
    int m=(l+r)>>1,re;
    if(m<p-1&&T[root*2+1]&&(re=pre(root*2+1,p,m+1,r)))
    return re;
    return pre(root*2,p,l,m);
}

int findn(int root,int l,int r){
    if(l==r) return l;
    int m=(l+r)>>1;
    if(T[root*2]) return findn(root*2,l,m);
    return findn(root*2+1,m+1,r);
}

int nex(int root,int p,int l,int r){
    if(p<l){
        if(T[root]) return findn(root,l,r);
        return 0;
    }
    int m=(l+r)>>1,re;
    if(p<m&&T[root*2]&&(re=nex(root*2,p,l,m)))
    return re;
    return nex(root*2+1,p,m+1,r);
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d%d",&opt[i],&t[i].v);
        t[i].p=i;
    }
    sort(t+1,t+1+n,cmp);
    a[t[1].p]=++e; 
    ma[a[t[1].p]]=t[1].v;
    for(int i=2;i<=n;i++){
        if(t[i].v!=t[i-1].v) ++e;
        a[t[i].p]=e;
        ma[a[t[i].p]]=t[i].v;
    }
    for(int i=1;i<=n;i++){
        if(opt[i]==1) update(1,a[i],1,1,e);
        else if(opt[i]==2) update(1,a[i],-1,1,e);
        else if(opt[i]==3) printf("%d\n",rank(1,a[i],1,e)+1);
        else if(opt[i]==4) printf("%d\n",ma[kth(1,ma[a[i]],1,e)]);
        else if(opt[i]==5) printf("%d\n",ma[pre(1,a[i],1,e)]);
        else printf("%d\n",ma[nex(1,a[i],1,e)]);
    }
    return 0;
}
View Code

 

RMQ

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=1e5+50;

int n,m,ma[maxn][26];

struct RMQ{
    int log2[maxn];
    void init(){
        for(int i=0;i<=n;i++) log2[i]=(i==0?-1:log2[i>>1]+1);
        for(int j=1;j<=20;j++)
        for(int i=1;i+(1<<j)-1<=n;i++) ma[i][j]=max(ma[i][j-1],ma[i+(1<<j-1)][j-1]);
    }
    int query(int ql,int qr){
        int k=log2[qr-ql+1];
        return max(ma[ql][k],ma[qr-(1<<k)+1][k]);
    }
}rmq;

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    read(n),read(m);
    for(int i=1;i<=n;i++) read(ma[i][0]);
    rmq.init();
    while(m--){
        int x,y;
        read(x),read(y);
        printf("%d\n",rmq.query(x,y));
    }
    return 0;
}
View Code

 

分块

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=500000+50;
const int maxblo=1000;

int bl[maxn],blo,n,a[maxn],m,sum[maxblo],tag[maxblo];

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    read(n);read(m);
    blo=sqrt(n);
    for(int i=1;i<=n;i++){
        read(a[i]);
        bl[i]=(i-1)/blo+1;
        sum[bl[i]]+=a[i];
    }
    while(m--){
        int op,x,y;
        read(op),read(x),read(y);
        if(op==1){
            a[x]+=y;
            sum[bl[x]]+=y;
        }
        else{
            int ans=0;
            for(int i=bl[x]+1;i<=bl[y]-1;i++) ans+=sum[i];
            for(int i=x;i<=bl[x]*blo;i++) ans+=a[i];
            for(int i=(bl[y]-1)*blo+1;i<=y;i++) ans+=a[i];
            printf("%d\n",ans);
        }
    }
    return 0;
}
View Code

 

并查集

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=10000+50;
const int maxm=200000+50;

int n,m,fat[maxn];

int father(int x){
    if(x!=fat[x]) fat[x]=father(fat[x]);
    return fat[x];
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    read(n),read(m);
    for(int i=1;i<=n;i++) fat[i]=i;
    while(m--){
        int x,y,op;
        read(op),read(x),read(y);
        int fa=father(x),fb=father(y);
        if(op==1){
            fat[fa]=fb;
        }
        else{
            if(fa==fb) cout<<"Y"<<endl;
            else cout<<"N"<<endl;
        }
    }
    return 0;
}
View Code

 


 

数学:

gcd / lcm

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

 

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

 

快速幂

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

int b,p,mod;

ll qsm(ll a,ll n){
    a%=mod;ll ans=1;
    for(ll i=n;i;i>>=1,a=(a*a)%mod)
    if(i&1) ans=(ans*a)%mod;
    return ans%mod;
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    read(b),read(p),read(mod);
    cout<<b<<"^"<<p<<" mod "<<mod<<"="<<qsm(b,p)<<endl;
    return 0;
}
View Code

 

快速乘

O(logn)

ll qsc(ll a,ll b,ll c){
    ll ans=0;
    a=a%c;
    b=b%c;
    while(b>0){
        if(b&1) ans=(ans+a)%c;
        a=(a+a)%c;
        b>>=1;
    }
    return ans;
}
View Code

 

O(1)

ll qsc(ll A,ll B,ll mod){
    return (A*B-(ll)((long double)A*B/mod)*mod+mod)%mod;
}
View Code

 

中国剩余定理

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

ll china(int n,int *a,int *m){    // x ≡ a[ i ] ( mod m[ i ] )  
    ll M=1,d,y,x=0;
    for(int i=1;i<=n;i++) M*=m[i];
    for(int i=1;i<=n;i++){
        ll w=M/m[i];
        exgcd(m[i],w,d,d,y);
        x=(x+y*w*a[i])%M;
    }
    return (x+M)%M;
}
View Code

 

线性筛素数

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long

int n,q,k;
bool isprime[100000010];
int prime[6000010],cnt=0;

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

template<typename T>void inline read(T &aa){
    ll ff=1;char cc=getchar();aa=0;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
    aa*=ff;
}

int main(){
    cin>>n>>q;
    Get(n);
    while(q--){
        read(k);
        printf("%d\n",prime[k]);
    }
    return 0;
}
View Code

 

根号n判素数

bool pd(int x){
    if(x==0||x==1) return false;
    for(int i=2;i*i<=x;i++)
    if(x%i==0) return false;
    return true;
}
普通版

 

bool pd(int x){
    if(x==0||x==1||x==4) return false;
    if(x==2||x==3) return true;
    if(x%6!=1&&x%6!=5) return false;
    if(x%2==0||x%3==0) return false;
    for(int i=5;i*i<=x;i+=6) 
    if(x%i==0||x%(i+2)==0) return false;
    return true;
}
小优化

 

线性筛欧拉函数

void sphi(int limit){
    phi[1]=1;
    for(int i=2;i<=limit;i++){
        if(!a[i]) prime[++tot]=i,phi[i]=i-1;
        for(int j=1;j<=tot&&i*prime[j]<=limit;j++){
            a[i*prime[j]]=1;
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
}
View Code

 

根号n求欧拉函数

ll PHI(ll x){
    ll ret=x;
    for(ll i=2;i*i<=x;i++)
    if(x%i==0){
        ret=ret-ret/i;
        while(x%i==0) x/=i;
    }
    if(x>1) ret=ret-ret/x;
    return ret;
}
View Code

 

基础算法

归并排序

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

const int maxn=5e5+50;

int c[maxn],d[maxn],n;ll ans;

void merge_sort(int l,int r){
    if(l==r) return ;
    int mid=l+r>>1,i,j,k;
    merge_sort(l,mid);merge_sort(mid+1,r);
    i=k=l;j=mid+1;
    while(i<=mid&&j<=r){
        if(c[i]<=c[j]) d[k++]=c[i++];
        else ans+=mid-i+1,d[k++]=c[j++];
    }
    while(i<=mid) d[k++]=c[i++];
    while(j<=r) d[k++]=c[j++];
    for(int i=l;i<=r;i++) c[i]=d[i];
}

int main(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>c[i];
    merge_sort(1,n);
    cout<<ans;
    return 0;
}
View Code

 

posted @ 2018-11-02 21:37  rld  阅读(228)  评论(0编辑  收藏  举报