ACM模版库制作V2

39 篇文章 0 订阅
14 篇文章 0 订阅

两天持续整理,整理了很多
也偷懒了很多
但是竟然NOIP提高就要整理嘛。
基础整理都出来的
方便复习,记忆代码
Doc版本也出来了。。
学校机房好烂。。。卡死了。。
难看死了。。
给个Doc吧。
http://pan.baidu.com/s/1bo0jgez
这里不能上传文件,我就弄弄吧。。。
Doc好看很多的

ACM
模板
目录
一、  图论
1.Spfa
(1).最短路
(2).次短路
    2.强连通
        (1).出入度操作
    3.并查集
        (1).简单并查集
        (2).功能并查集
        (3).倒推并查集
    4.网络流
        (1).简单构图
        (2).复杂构图
二、  树
1.  树状数组
(1) 简单
(2) 复杂
2.  线段树
(1) 维护只增数组
(2) 维护定量数组
(3) Lazy维护
3.  伸展树
(1) 普通伸展树操作
4.  最小生成树
(1) K算法
三、  数论
1.  快速幂
(1).gcd
(2).exgcd
(3).矩阵乘法
四、搜索
1.  Dfs
(1).简单
(2).复杂
2.  Bfs
五、DP
1.      一维
(1).简单
(2).复杂
2.      二维
(1).简单
(2).复杂









1.图论——Spfa
(1).最短路
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int x,y,c,next;
}a[210000];int len,first[5100];
bool v[5100];
int n,m;int d[5100],head,tail,list[5100];
void ins(int x,int y,int c){
    len++;
    a[len].x=x;a[len].y=y;a[len].c=c;
    a[len].next=first[x];first[x]=len;
}
void spfa(int st,int ed){
    memset(v,false,sizeof(v));v[st]=true;
    memset(d,63,sizeof(d));d[st]=0;
    head=1;tail=2;list[head]=st;
    while(head!=tail){
        int x=list[head];
        for(int k=first[x];k>0;k=a[k].next){
            int y=a[k].y;
            if(d[y]>d[x]+a[k].c){
                d[y]=d[x]+a[k].c;
                if(v[y]==false){
                    v[y]=true;
                    list[tail++]=y;
                    if(tail==n+1)tail=1;
                }
            }
        }
        v[x]=false;
        head++;if(head==n+1)head=1;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int x,y,c;
        scanf("%d%d%d",&x,&y,&c);
        ins(x,y,c);ins(y,x,c);
    }
    spfa(1,n);
    printf("%d\n",d[n]);
    return 0;
}
(2).次短路
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int x,y,c,next;
}a[210000];int len,first[5100];
bool v[5100];
int n,m;int d[5100],dd[5100],head,tail,list[5100];
void ins(int x,int y,int c){
    len++;
    a[len].x=x;a[len].y=y;a[len].c=c;
    a[len].next=first[x];first[x]=len;
}
void spfa(int st,int ed){
    memset(v,false,sizeof(v));v[st]=true;
    memset(d,63,sizeof(d));d[st]=0;

    head=1;tail=2;list[head]=st;
    while(head!=tail){
        int x=list[head];
        for(int k=first[x];k>0;k=a[k].next){
            int y=a[k].y;
            if(d[y]>d[x]+a[k].c){
                dd[y]=d[y];d[y]=d[x]+a[k].c;
                if(v[y]==false){
                    v[y]=true;
                    list[tail++]=y;if(tail==n+1)tail=1;
                }
            }
            if(dd[x]!=-1&&(dd[y]==-1||dd[y]>dd[x]+a[k].c)){
                dd[y]=dd[x]+a[k].c;
                if(v[y]==false){
                    v[y]=true;
                    list[tail++]=y;if(tail==n+1)tail=1;
                }  
            }
            else if(d[x]+a[k].c!=d[y]&&(dd[y]==-1||dd[y]>d[x]+a[k].c)){
                dd[y]=d[x]+a[k].c;
                if(v[y]==false){
                    v[y]=true;
                    list[tail++]=y;if(tail==n+1)tail=1;
                }
            } 
        }
        v[x]=false;
        head++;if(head==n+1)head=1;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int x,y,c;
        scanf("%d%d%d",&x,&y,&c);
        ins(x,y,c);ins(y,x,c);
    }
    spfa(1,n);
    printf("%d\n",dd[n]);
    return 0;
}
2.图论——强连通
(1).出入度操作
#include<set>
#include<map>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int x,y,next;
}a[110000];int len,first[11000],n,m;
void ins(int x,int y){
    len++;a[len].x=x;a[len].y=y;
    a[len].next=first[x];first[x]=len;
}
int sta[11000],tp;bool v[11000];
int cnt,belong[11000];
int low[11000],dfn[11000],id,num[11000];
int chu[11000],ru[11000];
void dfs(int x){
    low[x]=dfn[x]=++id;
    sta[++tp]=x;v[x]=true;
    for(int k=first[x];k>0;k=a[k].next){
        int y=a[k].y;
        if(dfn[y]==0){
            dfs(y);
            if(low[x]>low[y])low[x]=low[y];
        }
        else if(v[y]==true){
            if(low[x]>dfn[y])low[x]=dfn[y];
        }
    }
    if(low[x]==dfn[x]){
        cnt++;
        int i;
        do{ 
            i=sta[tp--];
            belong[i]=cnt; 
            v[i]=false;
        }while(i!=x);
    }
}
int main(){
    scanf("%d%d",&n,&m);
    len=0;memset(first,false,sizeof(first));
    cnt=0;memset(v,false,sizeof(v)); 
    memset(dfn,0,sizeof(dfn));
    tp=id=cnt=0;
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        ins(x,y);
    }
    for(int i=1;i<=n;i++)if(dfn[i]==0)dfs(i);
    memset(num,0,sizeof(num));
    for(int i=1;i<=n;i++)num[belong[i]]++;
    for(int i=1;i<=len;i++){
        if(belong[a[i].x]!=belong[a[i].y]){
            chu[belong[a[i].x]]++;
            ru[belong[a[i].y]]++;
        }
    }
    if(cnt==1){printf("%d\n",n);return 0;}
    int ans,zs=0;
    for(int i=1;i<=cnt;i++){
        if(chu[i]==0){
            zs++;ans=i;
        }
    }
    if(zs==1)printf("%d\n",num[ans]);
    else printf("0\n");
}
3.图论——并查集
(1).简单并查集
int findfa(int x){
    if(x==fa[x])return x;
    else return fa[x]=findfa(fa[x]);
}
(2).功能并查集
#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int n,fa[1100000];
bool v[1100000];
int findfa(int x){
    if(x==fa[x])return x;
    else return fa[x]=findfa(fa[x]);
}
void up(int x,int y){
    if(x<y)swap(x,y);
    v[y]=true;
    fa[y]=x;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n+1;i++)fa[i]=i;
    for(int i=1;i<=n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        int fx=findfa(x),fy=findfa(y);
        if(fx==fy)v[fx]=true;
        else up(fx,fy);
    }
    for(int i=1;i<=n+1;i++){
        if(v[i]==false){
            printf("%d\n",i-1);
            return 0;
        }
    }
    return 0;
}
(3).倒推并查集
#include<set>
#include<map>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int x,next;
}a[510000];//结构体,表示连接到x这个点 
int n,m,k,len,sum,f[510000],first[510000],fa[510000],ans[510000];
bool v[510000],b[510000];
void ins(int x,int y){
    len++;a[len].x=y;a[len].next=first[x];first[x]=len;
    len++;a[len].x=x;a[len].next=first[y];first[y]=len;//建边 
}   
int findfa(int x){
    if(x==fa[x])return fa[x];//找祖先 
    return fa[x]=findfa(fa[x]);
}
void add(int x){
    int xf=findfa(x);
    for(int k=first[x];k>0;k=a[k].next){ //v代表边现在存在 
        if(v[a[k].x]==true){
            int yf=findfa(a[k].x);
            if(xf!=yf){
                fa[yf]=x;sum--;//如果祖先不一样的话,统一祖先,联通块-1 
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)fa[i]=i;
    len=0;memset(first,0,sizeof(first));
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        ins(x,y);//建边不解释 
    }
    scanf("%d",&k);
    memset(b,false,sizeof(b));
    memset(v,false,sizeof(v));
    for(int i=1;i<=k;i++){
        scanf("%d",&f[i]);
        b[f[i]]=true;//如果不会被炸毁的先标记下来下边可以用上 
    }
    for(int i=0;i<n;i++){//是0到n-1,好坑爹 
        if(b[i]==false){//没被炸毁的先建边 
            sum++;add(i);
            v[i]=true;//建了边代表存在的 
        }
    }
    ans[k+1]=sum;//k+1代表最后炸毁的状态 
    for(int i=k;i>0;i--){
        sum++;//好,我们再模拟,一个一个把点加上去 
        add(f[i]);//加点 
        v[f[i]]=true;//很好这条边已经存在了 
        ans[i]=sum;//记录值 
    }
    for(int i=1;i<=k+1;i++)printf("%d\n",ans[i]);//输出 
}
3.图论——网络流
(1). 简单构图
略。
(2). 复杂构图
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int x,y,c,next,other;
}a[1100000];int len,first[1100000];
int n,m,d,list[1100000],head,tail,st,ed,K[1100][1100],ans,answer,h[1100000],Nh[1100][1100],Ch[1100][1100];
char s[1100];
double pd(int x,int y,int x1,int y1){
    return sqrt(double((x-x1)*(x-x1)+(y-y1)*(y-y1)));
}
void ins(int x,int y,int c){
    int xx,yy;
    len++;xx=len;
    a[len].x=x;a[len].y=y;a[len].c=c;
    a[len].next=first[x];first[x]=len;
    len++;yy=len;
    a[len].x=y;a[len].y=x;a[len].c=0;
    a[len].next=first[y];first[y]=len;
    a[xx].other=yy;
    a[yy].other=xx;
}
bool bt(){
    memset(h,0,sizeof(h));h[st]=1;
    list[1]=st;head=1;tail=2;
    while(head!=tail){
        int x=list[head];
        for(int k=first[x];k>0;k=a[k].next){
            int y=a[k].y;
            if(a[k].c>0&&h[y]==0){
                h[y]=h[x]+1;
                list[tail++]=y;
            }
        }
        head++;
    }
    if(h[ed]>0)return true;
    else return false;
}
int findflow(int x,int f){
    if(x==ed)return f;
    int s=0,tmp;
    for(int k=first[x];k>0;k=a[k].next){
        int y=a[k].y;
        if(a[k].c>0&&h[y]==h[x]+1&&s<f){
            tmp=findflow(y,min(a[k].c,f-s));
            s+=tmp;
            a[k].c-=tmp;a[a[k].other].c+=tmp;
        }
    }
    if(s==0)h[x]=0;
    return s;
}
int main(){
    scanf("%d%d%d",&n,&m,&d);
    st=0;ed=10001;
    len=0;memset(first,0,sizeof(first));
    for(int i=1;i<=n;i++){
        scanf("%s",s+1);
        for(int j=1;j<=m;j++){
            K[i][j]=s[j]-'0';
            Nh[i][j]=(m*(i-1)+j);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            Ch[i][j]=Nh[i][j]+n*m;
            if(K[i][j]>0)ins(Nh[i][j],Ch[i][j],K[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(i<=d||j<=d||i>=n-d+1||j>=m-d+1){
                ins(Ch[i][j],ed,999999999);
            }
        }
    }
    answer=0;
    for(int i=1;i<=n;i++){
        scanf("%s",s+1);
        for(int j=1;j<=m;j++){
            if(s[j]=='L'){
                answer++;ins(st,Nh[i][j],1);
            }
        } 
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            int n1,n2,n3,n4;
            n1=max(i-d,1);n2=min(i+d,n);
            n3=max(j-d,1);n4=min(j+d,m);
            for(int x=n1;x<=n2;x++){
                for(int y=n3;y<=n4;y++){
                    if(pd(i,j,x,y)<=d){
                        if(x!=i||y!=j){
                            ins(Ch[i][j],Nh[x][y],999999999);
                        }
                    }
                }
            }
        }
    }
    ans=0;
    while(bt()==true){
        ans+=findflow(st,999999999);
    }
    printf("%d\n",answer-ans);
    return 0;
} 
1.  树——树状数组
(1). 简单
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int x,y;
}a[1110000];
int cmp(const void *x1,const void *x2){
    node n1=*(node *)x1;
    node n2=*(node *)x2;
    if(n1.x!=n2.x)return n1.x-n2.x;
    else return n1.y-n2.y;
}
int s[1100],m;
int lowbit(int x) {
    return x & -x;
}
int qiuhe(int x){
    int ans=0;
    while(x>=1){
        ans+=s[x];
        x-=lowbit(x);
    }
    return ans;
}
void gaibian(int x,int k){
    while(x<=m){
        s[x]+=k;
        x+=lowbit(x);
    }
}
int main(){
    int i,k,n,t;long long ans;
    scanf("%d",&t);
    for(int ti=1;ti<=t;ti++){ 
        scanf("%d%d%d",&n,&m,&k);
        for(i=1;i<=k;i++){  
            scanf("%d%d",&a[i].x,&a[i].y);
        }
        qsort(a+1,k,sizeof(node),cmp);
        memset(s,0,sizeof(s));ans=0;
        for(i=1;i<=k;i++){
            ans+=qiuhe(m)-qiuhe(a[i].y);   
                gaibian(a[i].y,1);
        }
        printf("Test case %d: %I64d\n",ti,ans);
    }
    return 0;
}
(2). 复杂
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
int s[1100][1100],n; 
int lowbit(int x){  
    return x&(-x); 
} 
int qiuhe(int x,int y) {  
    int ans=0;  
    for(int i=x;i>0;i-=lowbit(i)){
        for(int j=y;j>0;j-=lowbit(j)){    
            ans+=s[i][j];   
        } 
    }
    return ans; 
} 
void gaibian(int x,int y,int k){  
    for(int i=x;i<=n;i+=lowbit(i)){
        for(int j=y;j<=n;j+=lowbit(j)){    
            s[i][j]+=k;   
        } 
    }
} 
int main(){  
    int t,x1,x2,y1,y2,a,b,m;  
    char st[12];  
    scanf("%d",&t);  
    while(t--){   
        memset(s,0,sizeof(s));   
        scanf("%d%d",&n,&m);   
        while(m--){    
            scanf("%s",st+1);    
            if(st[1]=='C')    {     
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);       
                gaibian(x1,y1,1);     
                gaibian(x1,y2+1,1);     
                gaibian(x2+1,y1,1);     
                gaibian(x2+1,y2+1,1);         
            }    
            else    {     
                scanf("%d%d",&a,&b);     
                printf("%d\n",qiuhe(a,b)%2);    
            }   
        }   
        printf("\n");  
    }  
    return 0; 
}
2.  树——线段树
(1). 维护只增数组
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree{
    int l,r,lc,rc,c;  
}tr[510000];
int trlen,n,l,len,t;
void bt(int l,int r){
    trlen++;int now=trlen;
    tr[now].l=l;tr[now].r=r;tr[now].c=0; 
    tr[now].lc=tr[now].rc=-1;
    if(l<r){
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
    }
}
void change(int now,int p,long long c){
    if(tr[now].l==tr[now].r){tr[now].c=c;return ;}
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(p<=mid)change(lc,p,c);
    else change(rc,p,c);
    tr[now].c=max(tr[lc].c,tr[rc].c);
}
int findmax(int now,int l,int r){
    if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;    
    if(mid+1<=l)return findmax(rc,l,r);
    else if(r<=mid)return findmax(lc,l,r);
    else return max(findmax(lc,l,mid),findmax(rc,mid+1,r));
}
int main(){
    scanf("%d%d",&n,&l);
    trlen=len=t=0;bt(1,210000);
    char s[10];long long x; 
    for(int i=1;i<=n;i++){
        scanf("%s%d",s,&x);
        if(s[0]=='A')change(1,++len,(x+t)%l);
        else{
            t=findmax(1,len-x+1,len);
            printf("%d\n",t);
        }
    }
}
(2). 维护定量数组
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int l,r,lc,rc,c;
}tr[510000];int trlen;
int a[110000];
void bt(int l,int r){
    trlen++;int now=trlen;
    tr[now].l=l;tr[now].r=r;tr[now].c=-1;
    tr[now].lc=tr[now].rc=-1;
    if(l==r)tr[now].c=a[l];
    else{
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
    }
}
void change(int now,int l,int r,int c){
    if(tr[now].c==c)return ;
    if(tr[now].l==l&&tr[now].r==r){tr[now].c=c;return ;}
    int mid=(tr[now].l+tr[now].r)/2,lc=tr[now].lc,rc=tr[now].rc;
    if(tr[now].c>0){
        tr[lc].c=tr[now].c;
        tr[rc].c=tr[now].c;
    }
    if(r<=mid)change(lc,l,r,c);
    else if(l>=mid+1)change(rc,l,r,c);
    else{
        change(lc,l,mid,c);
        change(rc,mid+1,r,c);
    }
    if(tr[lc].c>0&&tr[lc].c==tr[rc].c)tr[now].c=tr[lc].c;
    else tr[now].c=-1;
}
int color,ans;
void findcolor(int now,int l,int r){
    if(color==tr[now].c&&color!=-1)return ;
    int mid=(tr[now].l+tr[now].r)/2,lc=tr[now].lc,rc=tr[now].rc;
    if(tr[now].l==l&&tr[now].r==r){
        if(tr[now].c==-1){
            findcolor(lc,l,mid);findcolor(rc,mid+1,r);
        }
        else if(tr[now].c>0&&tr[now].c!=color){
            ans++;color=tr[now].c;
        }
        return ;
    }
    if(tr[now].c>0){
        tr[lc].c=tr[now].c;tr[rc].c=tr[now].c;
    }
    if(r<=mid)findcolor(lc,l,r);
    else if(l>=mid+1)findcolor(rc,l,r);
    else{
        findcolor(lc,l,mid);
        findcolor(rc,mid+1,r);
    }
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    trlen=0;bt(1,n);
    int t,x,y,k;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&t,&x,&y);
        if(x>y)swap(x,y);
        if(t==1){
            scanf("%d",&k);
            change(1,x,y,k);
        }
        else{
            ans=0;color=-1;
            findcolor(1,x,y);
            printf("%d\n",ans);
        }
    }
    return 0;
}
(3). Lazy维护 
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree{
    int l,r,lc,rc;
    long long c,lazy;  
}tr[510000];
int trlen,n,m,len;
long long a[210000];
void bt(int l,int r){
    trlen++;int now=trlen;
    tr[now].l=l;tr[now].r=r;
    tr[now].c=0;tr[now].lazy=0;
    tr[now].lc=tr[now].rc=-1;
    if(l==r)tr[now].c=a[l];
    else{
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
        tr[now].c=tr[tr[now].lc].c+tr[tr[now].rc].c;
    }
}
void change(int now,int x,int y,long long c){
    tr[now].c+=(y-x+1)*c;
    if(tr[now].l==x&&tr[now].r==y){
        tr[now].lazy+=c;return ;
    }
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(y<=mid)change(lc,x,y,c);
    else if(x>=mid+1)change(rc,x,y,c);
    else{
        change(lc,x,mid,c);
        change(rc,mid+1,y,c);
    }
}
long long findsum(int now,int l,int r){
    if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;   
    if(tr[now].lazy!=0){
        tr[lc].c+=tr[now].lazy*(tr[lc].r-tr[lc].l+1);
        tr[rc].c+=tr[now].lazy*(tr[rc].r-tr[rc].l+1);
        tr[lc].lazy+=tr[now].lazy;
        tr[rc].lazy+=tr[now].lazy;
        tr[now].lazy=0;
    }
    if(l>=mid+1)return findsum(rc,l,r);
    else if(r<=mid)return findsum(lc,l,r);
    else return findsum(lc,l,mid)+findsum(rc,mid+1,r);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    trlen=0;bt(1,n);
    scanf("%d",&m);
    int s,x,y;long long z; 
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&s,&x,&y);
        if(s==1){
            scanf("%lld",&z);
            change(1,x,y,z);
        }
        else{
            printf("%lld\n",findsum(1,x,y));
        }
    }
}
3.  树——伸展树
(1). 普通伸展树操作
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int d,n,c,f,son[2]; 
}tr[110000];int len,root;
void update(int x){tr[x].c=tr[tr[x].son[0]].c+tr[tr[x].son[1]].c+tr[x].n;}
void add(int d,int f){
    tr[++len].d=d;tr[len].n=tr[len].c=1;
    tr[len].f=f;if(d<tr[f].d)tr[f].son[0]=len;else tr[f].son[1]=len;
    tr[len].son[0]=tr[len].son[1]=0;        
}
void rotate(int x,int w){
    int f=tr[x].f,ff=tr[f].f,r,R;   
    r=tr[x].son[w];R=f;
    tr[R].son[1-w]=r;
    if(r!=0)tr[r].f=R;
    r=x;R=ff;
    if(tr[R].son[0]==f)tr[R].son[0]=r;else tr[R].son[1]=r;
    tr[r].f=R;
    r=f;R=x;
    tr[R].son[w]=r;
    tr[r].f=R;
    update(f);
    update(x);
}
void splay(int x,int rt){
    while(tr[x].f!=rt){
        int f=tr[x].f,ff=tr[f].f;
        if(ff==rt)if(tr[f].son[0]==x)rotate(x,1);else rotate(x,0);
        else{
                 if(tr[ff].son[0]==f&&tr[f].son[0]==x){rotate(f,1);rotate(x,1);}
            else if(tr[ff].son[1]==f&&tr[f].son[1]==x){rotate(f,0);rotate(x,0);}    
            else if(tr[ff].son[0]==f&&tr[f].son[1]==x){rotate(x,0);rotate(x,1);}
            else if(tr[ff].son[1]==f&&tr[f].son[0]==x){rotate(x,1);rotate(x,0);}
        }
    }
    if(rt==0)root=x;
}
int findip(int d){
    int x=root;
    while(tr[x].d!=d){
        if(d<tr[x].d){
            if(tr[x].son[0]==0)break;
            else x=tr[x].son[0];
        }
        else{
            if(tr[x].son[1]==0)break;
            else x=tr[x].son[1];
        }
    }
    return x;
}
void ins(int d){
    if(root==0){add(d,0);root=len;return ;}
    int x=findip(d);
    if(tr[x].d==d){
        tr[x].n++;
        update(x);
        splay(x,0);     
    }
    else{
        add(d,x);
        update(x);
        splay(len,0);   
    }
}
void del(int d){
    int x=findip(d);splay(x,0);
    if(tr[x].n>1){tr[x].n--;update(x);return ;}
    else if(tr[x].son[0]==0&&tr[x].son[1]==0){root=len=0;}
    else if(tr[x].son[0]==0&&tr[x].son[1]!=0){root=tr[x].son[1];tr[root].f=0;}
    else if(tr[x].son[0]!=0&&tr[x].son[1]==0){root=tr[x].son[0];tr[root].f=0;}
    else{
        int p=tr[x].son[0];while(tr[p].son[1]!=0)p=tr[p].son[1];splay(p,x);
        int r=tr[x].son[1],R=p;
        tr[R].son[1]=r;tr[r].f=R;
        root=R;tr[root].f=0;update(R);  
    }
}
void findpaiming(int d){
    int x=findip(d);splay(x,0);
    printf("%d\n",tr[tr[x].son[0]].c+1);    
}
void findshuzi(int k){
    int x=root;
    while(1){
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if(k<=tr[lc].c)x=lc;
        else if(k>tr[lc].c+tr[x].n){k-=tr[lc].c+tr[x].n;x=rc;}
        else break;
    }
    splay(x,0);
    printf("%d\n",tr[x].d);
}
int findqianqu(int d){
    int x=findip(d);splay(x,0);
    if(d<=tr[x].d && tr[x].son[0]!=0){
        x=tr[x].son[0];
        while(tr[x].son[1]!=0)x=tr[x].son[1];
    }
    if(tr[x].d>=d)x=0;
    return x;
}
int findhouji(int d){
    int x=findip(d);splay(x,0);
    if(tr[x].d<=d && tr[x].son[1]!=0){
        x=tr[x].son[1];
        while(tr[x].son[0]!=0)x=tr[x].son[0];
    }
    if(tr[x].d<=d)x=0;
    return x;
}
int main(){
    int n;
    scanf("%d",&n);
    root=0;len=0;
    for(int i=1;i<=n;i++){
        int cz,x;scanf("%d%d",&cz,&x);
        if(cz==1)ins(x);
        else if(cz==2)del(x);
        else if(cz==3)findpaiming(x);
        else if(cz==4)findshuzi(x);
        else if(cz==5)printf("%d\n",tr[findqianqu(x)].d);
        else if(cz==6)printf("%d\n",tr[findhouji(x)].d);
    }
}
4.  树——最小生成树
(1). K算法
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,fa[11000],len,maxx,fx,fy,ans;
int findfa(int x){
    if(fa[x]!=x)fa[x]=findfa(fa[x]);
    return fa[x];
}
struct edge{
    int x,y,d;
}e[11000];
int cmp(const void *xx,const void *yy){
    edge n1=*(edge *)xx;
    edge n2=*(edge *)yy;
    return n1.d-n2.d;
}
int main(){
    scanf("%d%d",&n,&m); 
    for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].d);
    qsort(e+1,m,sizeof(edge),cmp);
    for(int i=1;i<=n;i++)fa[i]=i;
    ans=0;
    for(int i=1;i<=m;i++){
        fx=findfa(e[i].x);fy=findfa(e[i].y);
        if(fx!=fy){
            fa[fx]=fy;
            ans++;
            if(ans==n-1){
                maxx=e[i].d; 
                break;
            }
        }
    }
    printf("%d %d\n",ans,maxx);
}
1.数论——快速幂
(1). Gcd
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int gcd(int a,int b){
    if(a==0)return b;
    else return gcd(b%a,a); 
}
int main(){
    int x,y;
    scanf("%d%d",&x,&y);
    printf("%d\n",gcd(x,y));
}
(2).exgcd
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
//a+c*x=b(mod 2^k) c*x=(b-a)(mod 2^k) c*x-2*k*y=b-a
long long exgcd(long long a,long long b,long long &x,long long &y){
    if(a==0){
        x=0;y=1;
        return b;
    }
    else{ 
        long long tx,ty;
        long long d=exgcd(b%a,a,tx,ty);
        x=ty-(b/a)*tx;
        y=tx;
        return d; 
    }
}
int main(){
    long long a,b,c,k,x,y;
    while(scanf("%lld%lld%lld%lld",&a,&b,&c,&k)!=EOF){
        if(a==0&&b==0&&c==0&&k==0)break;
        long long A=c,B=1LL<<k,K=b-a;
        long long d=exgcd(A,B,x,y);
        if(K%d!=0)printf("FOREVER\n");
        else printf("%lld\n",((x*K/d)%(B/d)+(B/d))%(B/d));
    }
}
(3). 矩阵乘法
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int n,mod=1000000007;
struct node{
    long long a[4][4];
    node(){
        memset(a,0,sizeof(a));
    }
}; 
node chengfa(node a,node b) { 
    node c; 
    for(int i=1;i<=3;i++){
        for(int j=1;j<=3;j++){ 
            for(int k=1;k<=3;k++){ 
                c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
            }
        }
    }
    return c;    
}
int main(){ 
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n); 
        node ans,A;  
        ans.a[1][1]=1;ans.a[2][1]=1;ans.a[3][1]=1;
        A.a[1][1]=0;A.a[1][2]=0;A.a[1][3]=1;
        A.a[2][1]=1;A.a[2][2]=0;A.a[2][3]=0;
        A.a[3][1]=0;A.a[3][2]=1;A.a[3][3]=1; 
        while(n>0){ 
            if(n%2==1)ans=chengfa(ans,A); 
            A=chengfa(A,A); 
            n/=2; 
        } 
        printf("%d\n",ans.a[3][3]%mod);
    }
} 
1.  搜索——Dfs
(1). 简单
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int s[21][21][21];
bool v[21][21][21];
int a1,b1,c1;
int dfs(int a,int b,int c){
    int ans=0;
    if(v[a][b][c]==true){
        return s[a][b][c];
    }
    else if(a<=0||b<=0||c<=0)return 1;
    else if(a<b&&b<c)ans=dfs(a,b,c-1)+dfs(a,b-1,c-1)-dfs(a,b-1,c);
    else ans=dfs(a-1,b,c)+dfs(a-1,b-1,c)+dfs(a-1,b,c-1)-dfs(a-1,b-1,c-1);
    v[a][b][c]=true;
    s[a][b][c]=ans;
    return ans;
}
int main(){
    while(scanf("%d%d%d",&a1,&b1,&c1)!=EOF){
        if(a1==-1&&b1==-1&&c1==-1)return 0;
        else if(a1<=0||b1<=0||c1<=0)printf("w(%d, %d, %d) = 1\n",a1,b1,c1);
        else if(a1>20||b1>20||c1>20) printf("w(%d, %d, %d) = %d\n",a1,b1,c1,dfs(20,20,20));
        else printf("w(%d, %d, %d) = %d\n",a1,b1,c1,dfs(a1,b1,c1));
    }
    return 0;
}
(2). 复杂
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int X,Y,K;
double dfs(double x,double y,int k){
    double ans=999999999.0,sum;
    if(k==1){
        return max(x,y)/min(x,y);
    }
    else{
        for(int i=1;i<k;i++){
            sum=0.0;
            sum=max(sum,dfs((x/k)*i,y,i));
            sum=max(sum,dfs(x-((x/k)*i),y,k-i));
            ans=min(sum,ans);
            sum=0.0;
            sum=max(sum,dfs(x,(y/k)*i,i));
            sum=max(sum,dfs(x,(y-(y/k)*i),k-i));
            ans=min(sum,ans);
        }
    }
    return ans;
}
int main(){
    scanf("%d%d%d",&X,&Y,&K);
    printf("%.6lf",dfs(X,Y,K));
}
2.  搜索——Bfs
如Spfa 略 =.=
1.DP——一维
(1). 简单
#include<cmath> 
#include<cstdio> 
#include<cstring> 
#include<cstdlib> 
#include<iostream> 
#include<algorithm> 
using namespace std; 
int n,ans; 
int main(){ 
scanf("%d",&n);ans=0; 
for(int i=n-1;i>=1;i--)ans=ans+i;ans-=n-1; 
printf("%d\n",ans); 
return 0; 
} 
(2). 复杂
#include<cmath> 
#include<cstdio> 
#include<cstring> 
#include<cstdlib> 
#include<iostream> 
#include<algorithm> 
using namespace std; 
int n;double k,c,w,ans; 
struct ek{  
    int k;double c; 
}e[110000]; 
int main(){ 
    scanf("%d%lf%lf%lf",&n,&k,&c,&w); 
    for(int i=1;i<=n;i++)scanf("%d%lf",&e[i].k,&e[i].c); 
    ans=0.0; 
    for(int i=n;i>=1;i--){ 
        if(e[i].k==1){ 
            ans=max(ans,(ans*(1-k/100.0)+e[i].c*w)); 
        } 
        else{ 
            ans=max(ans,(ans*(1+c/100.0)-e[i].c*w)); 
        } 
    } 
    printf("%.2lf\n",ans); 
    return 0; 
} 
2.DP——二维
(1). 简单
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib> 
#include<iostream>
#include<algorithm>
using namespace std;
long long f[5100][5100],n,r,x,y,z,ans=0;
int main(){
    scanf("%lld%lld",&n,&r);  
    memset(f,0,sizeof(f));  
    if(r==0){
        printf("0\n");
        return 0;
    }  
    for(int i=1;i<=n;i++){
        scanf("%lld%lld%lld",&x,&y,&z);
        f[x+1][y+1]=z;
    }
    for(int i=1;i<=5001;i++){
        for(int j=1;j<=5001;j++)f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
    }
    for(int i=r;i<=5001;i++){
        for(int j=r;j<=5001;j++){
            ans=max(ans,f[i][j]-f[i-r][j]-f[i][j-r]+f[i-r][j-r]);
        }
    }
    printf("%lld\n",ans);
}
(2)复杂
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
long long f[5100][5100],n,r,x,y,z,ans=0;
int main(){
    scanf("%lld%lld",&n,&r);  
    memset(f,0,sizeof(f));  
    if(r==0){
        printf("0\n");
        return 0;
    }  
    for(int i=1;i<=n;i++){
        scanf("%lld%lld%lld",&x,&y,&z);
        f[x+1][y+1]=z;
    }
    for(int i=1;i<=5001;i++){
        for(int j=1;j<=5001;j++)f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
    }
    for(int i=r;i<=5001;i++){
        for(int j=r;j<=5001;j++){
            ans=max(ans,f[i][j]-f[i-r][j]-f[i][j-r]+f[i-r][j-r]);
        }
    }
    printf("%lld\n",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值