洛谷P1001 A+B problem最全算法

为防止大家说我误导新人,先放一个最 正常的代码。

#include <iostream>
using namespace std;
int main() {
    int a,b;
    cin >> a >> b;
    cout << a+b;
    return 0;
}

接下来正文开始!!!

很正常的快读:

#include<bits/stdc++.h>
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define inf 0x7fffffff
#define INF 0x3f
#define v e[i].y
using namespace std;
inline ll read(){
    char ch=getchar();ll x=0,w=1;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();return w==1?x:-x;
}
inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x<10){putchar(48+x);return;}
    write(x/10),putchar((x+10)%10+48);
}
int a=read(),b=read();
int main(){
    write(a+b);
    return 0;
}

然后我会逐渐走向不正常,大家最想看的网络流,平衡树等算法我会在后面写,不要着急(心急的可以拉到后面看)。

普及组的算法(正文的铺垫,大佬们先吃些小菜开开胃):

逻辑运算:

#include<bits/stdc++.h>
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define inf 0x7fffffff
#define INF 0x3f
#define v e[i].y
using namespace std;
inline ll read(){
    char ch=getchar();ll x=0,w=1;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();return w==1?x:-x;
}
inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x<10){putchar(48+x);return;}
    write(x/10),putchar((x+10)%10+48);
}
int a=read(),b=read();
int main(){
    write((a|b)+(a&b));
    return 0;
}

高精度:

//好吧,本题因为数有正负,除了正数的高精加外,还需要写判断大小与高精减的代码,本人表示我就算写了(还有一个原因是懒得写),大佬们也不想看,还是把精彩留给后面那些高级的算法吧。

递推(或者算是前缀和,线性dp?):

#include<bits/stdc++.h>
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define inf 0x7fffffff
#define INF 0x3f
#define v e[i].y
using namespace std;
inline ll read(){
    char ch=getchar();ll x=0,w=1;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();return w==1?x:-x;
}
inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x<10){putchar(48+x);return;}
    write(x/10),putchar((x+10)%10+48);
}
int n,sum[10];
int main(){
    n=2;
    for(int i=1;i<=n;i++)sum[i]=read()+sum[i-1];
    write(sum[n]);
    return 0;
}

背包:

#include<bits/stdc++.h>
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define inf 0x7fffffff
#define INF 0x3f
#define v e[i].y
using namespace std;
inline ll read(){
    char ch=getchar();ll x=0,w=1;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();return w==1?x:-x;
}
inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x<10){putchar(48+x);return;}
    write(x/10),putchar((x+10)%10+48);
}
ll n,dp[10],a[10],b[10],V;
int main(){
    n=2,V=2;
    for(int i=1;i<=V;i++)dp[i]=-linf;
    for(int i=1;i<=n;i++)a[i]=1,b[i]=read();
    for(int i=1;i<=n;i++)
        for(int j=V;j>=a[i];j--)
            dp[j]=max(dp[j],dp[j-a[i]]+b[i]);
    write(dp[V]);
    return 0;
}

区间 dp:

#include<bits/stdc++.h>
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define inf 0x7fffffff
#define INF 0x3f
#define v e[i].y
using namespace std;
inline ll read(){
    char ch=getchar();ll x=0,w=1;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();return w==1?x:-x;
}
inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x<10){putchar(48+x);return;}
    write(x/10),putchar((x+10)%10+48);
}
ll n,dp[10][10],a[10];
int main(){
    n=2;
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
            dp[i][j]=-linf;
    for(int i=1;i<=n;i++)a[i]=read(),dp[i][i]=a[i];
    for(int i=n-1;i>=1;i--)
        for(int j=i+1;j<=n;j++)
            dp[i][j]=max(dp[i][j-1]+a[j],dp[i+1][j]+a[i]);
    write(dp[1][n]);
    return 0;
}

好,普及组的算法应该结束了吧,如果我硬套出什么二分,贪心之类的想必大佬们也会反感的吧。我之所以写上面这些基础算法,就是为了防止某些人问我:“你写这么多行干什么呢?你会动规,递推···吗”那么我就跟你们说,我会(滑稽

大菜来了:

倍增表:

#include<bits/stdc++.h>
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define inf 0x7fffffff
#define INF 0x3f
#define v e[i].y
using namespace std;
inline ll read(){
    char ch=getchar();ll x=0,w=1;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();return w==1?x:-x;
}
inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x<10){putchar(48+x);return;}
    write(x/10),putchar((x+10)%10+48);
}
ll n,st[10][10];
int main(){
    n=2;
    for(int i=1;i<=n;i++)st[i][0]=read();
    for(int i=1;i<=1;i++)//虽说这么写没什么意义,但还是遵循平常写ST表的格式吧
        for(int j=1;j<=n-(1<<i)+1;j++)
            st[j][i]=st[j][i-1]+st[j+(1<<i-1)][i-1];
    write(st[1][1]);
    return 0;
}

树状数组:

#include<bits/stdc++.h>
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define inf 0x7fffffff
#define INF 0x3f
#define v e[i].y
using namespace std;
inline ll read(){
    char ch=getchar();ll x=0,w=1;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();return w==1?x:-x;
}
inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x<10){putchar(48+x);return;}
    write(x/10),putchar((x+10)%10+48);
}
ll n,a[10];
struct BIT{
    ll c[10];
    ll lowbit(int x){return x&-x;}
    void add(int x,int V){for(;x<=n;x+=lowbit(x))c[x]+=V;}
    ll query(int x){ll res=0;for(;x;x-=lowbit(x))res+=c[x];return res;}
}A;
int main(){
    n=2;
    for(int i=1;i<=n;i++)a[i]=read(),A.add(i,a[i]);
    write(A.query(n)-A.query(0));
    return 0;
}

线段树:

#include<bits/stdc++.h>
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define inf 0x7fffffff
#define INF 0x3f
#define v e[i].y
using namespace std;
inline ll read(){
    char ch=getchar();ll x=0,w=1;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();return w==1?x:-x;
}
inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x<10){putchar(48+x);return;}
    write(x/10),putchar((x+10)%10+48);
}
ll n,a[10];
struct sgt{
    //只需要pushup和build的segment tree简单爆了
    ll sum[100];
    void pushup(int o){sum[o]=sum[o<<1]+sum[o<<1|1];}
    void build(int o,int l,int r){
        if(l==r){sum[o]=a[l];return;}
        int mid=l+r>>1;
        build(o<<1,l,mid),build(o<<1|1,mid+1,r);
        pushup(o);
    }
}A;
int main(){
    n=2;
    for(int i=1;i<=n;i++)a[i]=read();
    A.build(1,1,n),write(A.sum[1]);
    return 0;
}

字典树:

#include<bits/stdc++.h>
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define inf 0x7fffffff
#define INF 0x3f
#define v e[i].y
using namespace std;
inline ll read(){
    char ch=getchar();ll x=0,w=1;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();return w==1?x:-x;
}
inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x<10){putchar(48+x);return;}
    write(x/10),putchar((x+10)%10+48);
}
ll n,ans;
struct trie{
    //做法:01trie
    //结点数字*对应权值就是一个结点的数值,数值和就是答案
    int ch[100][2],val[100],a[100],num;
    void Insert(int x){
        int op=0,w=(x<0?-1:1);
        x=abs(x);
        for(int i=30;i>=0;i--){
            bool j=(x&(1<<i));
            op=(ch[op][j]?ch[op][j]:ch[op][j]=++num);
            val[op]+=w,a[op]=j*(1<<i);
        }
    }
}A;
int main(){
    n=2;
    for(int i=1;i<=n;i++)A.Insert(read());
    for(int i=1;i<=A.num;i++)ans+=A.val[i]*A.a[i];
    write(ans);
    return 0;
}

平衡树(fhq treap):

//因为各种平衡树都差不多,所以这里就只放一种了。
#include<bits/stdc++.h>
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define inf 0x7fffffff
#define INF 0x3f
#define v e[i].y
using namespace std;
inline ll read(){
    char ch=getchar();ll x=0,w=1;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();return w==1?x:-x;
}
inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x<10){putchar(48+x);return;}
    write(x/10),putchar((x+10)%10+48);
}
int n;
struct fhqtreap{
    #define lc ch[o][0]
    #define rc ch[o][1]
    int ch[100005][2],si[100005],rd[100005],val[100005],rt,num,r1,r2,r3;
    int newnode(int V){num++,si[num]=1,rd[num]=rand(),val[num]=V;return num;}
    void pushup(int o){si[o]=si[lc]+si[rc]+1;}
    void Split(int o,int V,int &A,int &B){//这个最容易写错
        if(!o){A=B=0;return;}
        if(V>=val[o])A=o,Split(rc,V,rc,B);
        else B=o,Split(lc,V,A,lc);
        pushup(o);
    }
    int Merge(int A,int B){
        if(!A||!B)return A+B;
        if(rd[A]<rd[B]){ch[A][1]=Merge(ch[A][1],B),pushup(A);return A;}
        else{ch[B][0]=Merge(A,ch[B][0]),pushup(B);return B;}
    }
    void Insert(int V){
        r1=r2=r3=0;
        Split(rt,V,r1,r2);
        rt=Merge(Merge(r1,newnode(V)),r2);
    }
    /*
    void Erase(int V){
        r1=r2=r3=0;
        Split(rt,V,r1,r3),Split(r1,V-1,r1,r2);
        rt=Merge(Merge(r1,Merge(ch[r2][0],ch[r2][1])),r3);
    }
    int queV(int V){
        r1=r2=r3=0;
        Split(rt,V-1,r1,r2);
        int ans=si[r1]+1;
        rt=Merge(r1,r2);
        return ans;
    }
    */
    int quek(int R,int k){
        while(1){
            if(k<=si[ch[R][0]])R=ch[R][0];
            else if(si[ch[R][0]]+1==k)return R;
            else k-=(si[ch[R][0]]+1),R=ch[R][1];
        }
    }
    /*
    int pre(int V){
        r1=r2=r3=0;
        Split(rt,V-1,r1,r2);
        int ans=val[quek(r1,si[r1])];
        rt=Merge(r1,r2);
        return ans;
    }
    int nxt(int V){
        r1=r2=r3=0;
        Split(rt,V,r1,r2);
        int ans=val[quek(r2,1)];
        rt=Merge(r1,r2);
        return ans;
    }
    */
    void solve(){
        int opt,x;
        for(int i=1;i<=2;i++){
            x=read();
            Insert(x);
        }
        int ans=0;
        for(int i=1;i<=2;i++)ans+=val[quek(rt,i)];
        write(ans);
    }
}A;
int main(){
    A.solve();   
    return 0;
}

未完待续

posted @ 2022-08-25 15:27  mcDinic  阅读(605)  评论(0编辑  收藏  举报