1. 程式人生 > >整理的各種模板 (隨時棄坑emmmmm)

整理的各種模板 (隨時棄坑emmmmm)

esp print scan algorithm include 優化 down lazy algo

線段樹:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define lson rt<<1
#define rson rt<<1|1
#define ll long long
using namespace std;
inline ll read()
{
    char c=getchar();ll num=0,f=1;
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) num=num*10+c-‘0‘;
    return num*f;
}
const ll N=1e5+5;
ll n,m;
ll a[N];
struct Tree
{
    ll len;                   //記錄掌管的區間的長度數(元素個數 
    ll maxn,minn,sum;         //最大最小值、區間和 
    ll lazy;                  //lazy標記 
}tree[N<<2];
inline void pushup(ll rt)     //用兒子更新當前節點 
{
    tree[rt].maxn=max(tree[lson].maxn,tree[rson].maxn);
    tree[rt].minn=min(tree[lson].minn,tree[rson].minn);
    tree[rt].sum=tree[lson].sum+tree[rson].sum;
    return;
}
void build(ll rt,ll l,ll r)    //rt為當前的樹根,l,r為rt對應的區間 
{
    tree[rt].len=r-l+1;        //當前節點掌管的區間長度(元素個數 
    if(l==r)                   //建到葉子節點了 
    {
        tree[rt].maxn=a[l];    //rt就是位置l對應的節點 
        tree[rt].minn=a[l];
        tree[rt].sum=a[l];
        return;
    }
    ll mid=(l+r)>>1;
    build(lson,l,mid);          //建左兒子rt*2,對應區間[l,mid] 
    build(rson,mid+1,r);        //建右兒子rt*2+1,對應區間[mid+1,r] 
    pushup(rt);                 //更新當前區間 
}
inline void pushdown(ll rt)     //下傳lazy標記 
{
    if(tree[rt].lazy)
    {
        //更新孩子的lazy標記 
        tree[lson].lazy+=tree[rt].lazy;
        tree[rson].lazy+=tree[rt].lazy;
        //更新孩子的最大值 
        tree[lson].maxn+=tree[rt].lazy;
        tree[rson].maxn+=tree[rt].lazy;
        //更新孩子的最小值 
        tree[lson].minn+=tree[rt].lazy;
        tree[rson].minn+=tree[rt].lazy;
        //更新孩子的區間和 
        tree[lson].sum+=tree[rt].lazy*tree[lson].len;
        tree[rson].sum+=tree[rt].lazy*tree[rson].len;
        //lazy重置 
        tree[rt].lazy=0;
    }
    return;
}
void modify(ll rt,ll l,ll r,ll pos,ll val)  //單點修改 
{
    if(l==r)    //找到pos對應的葉子節點了 
    {
        tree[rt].maxn+=val;
        tree[rt].minn+=val;
        tree[rt].sum+=val;
        return;
    }
    pushdown(rt);                 //下放當前區間lazy標記
    ll mid=(l+r)>>1;
    if(pos<=mid)                  //pos在左兒子裏 
        modify(lson,l,mid,pos,val);
    else                       //在右兒子裏 
        modify(rson,mid+1,r,pos,val); 
    pushup(rt);                 //更新當前區間 
}
void Modify(ll rt,ll l,ll r,ll L,ll R,ll val)   //區間修改 
{
    if(l==L&&r==R)  //找到一個合法區間 
    {
        tree[rt].sum+=tree[rt].len*val;
        tree[rt].maxn+=val;
        tree[rt].minn+=val;
        tree[rt].lazy+=val;
        return;
    }
    pushdown(rt);
    ll mid=(l+r)>>1;
    if(R<=mid)
        Modify(lson,l,mid,L,R,val);
    else if(L>mid)
        Modify(rson,mid+1,r,L,R,val);
    else
        Modify(lson,l,mid,L,mid,val),Modify(rson,mid+1,r,mid+1,R,val);
    pushup(rt);                               //不要忘了pushup 
}
ll query_sum(ll rt,ll l,ll r,ll L,ll R)         //查詢區間和 
{
    if(l==L&&r==R)                           //找到了一個合法區間,返回區間和 
        return tree[rt].sum;
    pushdown(rt);
    ll mid=(l+r)>>1;
    if(R<=mid)                              //查詢區間全在左子樹 
        return query_sum(lson,l,mid,L,R);
    else if(L>mid)                          //查詢區間全在右子樹 
        return query_sum(rson,mid+1,r,L,R);
    else                                     //一塊在左子樹,一塊在右子樹 
        return query_sum(lson,l,mid,L,mid)+query_sum(rson,mid+1,r,mid+1,R);
}
ll query_max(ll rt,ll l,ll r,ll L,ll R)
{
    if(l==L&&r==R)
        return tree[rt].maxn;
    pushdown(rt);
    ll mid=(l+r)>>1;
    if(R<=mid)
        return query_max(lson,l,mid,L,R);
    else if(L>mid)
        return query_max(rson,mid+1,r,L,R);
    else
        return max(query_max(lson,l,mid,L,mid),query_max(rson,mid+1,r,L,R));
}
ll query_min(ll rt,ll l,ll r,ll L,ll R)
{
    if(l==L&&r==R)
        return tree[rt].minn;
    pushdown(rt);
    ll mid=(l+r)>>1;
    if(R<=mid)
        return query_min(lson,l,mid,L,R);
    else if(L>mid)
        return query_min(rson,mid+1,r,L,R);
    else
        return min(query_min(lson,l,mid,L,mid),query_min(rson,mid+1,r,L,R));
};
ll opt;
ll x,l,r,val;
int main()
{
    n=read(),m=read();
    for(ll i=1;i<=n;++i)
        a[i]=read();
    build(1,1,n);
    while(m--)
    {
        opt=read();
        if(opt==2)
        {
            l=read(),r=read();
            cout<<query_sum(1,1,n,l,r)<<‘\n‘;
        }
        else if(opt==1)
        {
            l=read(),r=read(),val=read();
            Modify(1,1,n,l,r,val);
        }
    }
    return 0;
}

st表:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,f[100005][33],lg[100005];
int main()
{
    scanf("%d%d",&n,&m);
    lg[0]=-1;
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&f[i][0]);
        lg[i]=lg[i>>1]+1;
    }
    for(int j=1;j<=19;++j)
    {
        for(int i=1;i+(1<<j)-1<=n;++i)
        {
            f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }
    }
    for(int i=1,l,r;i<=m;++i)
    {
        scanf("%d%d",&l,&r);
        int k=lg[r-l+1];
        cout<<max(f[l][k],f[r-(1<<k)+1][k])<<"\n";
    }
    return 0;
}

dijkstra(O(n2)):

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio> 
#define maxn 500000+1
#define maxn1 10000+1
using namespace std;
inline int qread()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) num=num*10+c-‘0‘;
    return num*f;
}
struct Edge
{
    int v,w,nxt;
}edge[maxn];
int head[maxn],num;
void ct(int u,int v,int w)
{
    edge[++num].v=v;
    edge[num].w=w;
    edge[num].nxt=head[u];
    head[u]=num;
}
int n,m,s;
int dis[maxn1],vis[maxn1];
void dijkstra()
{
    dis[s]=0;
    for(int i=1;i<=n;++i)
    {
        int minn=0x7fffffff,u=-1;
        for(int j=1;j<=n;++j)
        {
            if(!vis[j]&&dis[j]<minn)
              minn=dis[j],u=j;
        }
        if(u==-1) break;
        vis[u]=1;
        for(int j=head[u];j;j=edge[j].nxt)
        {
            int v=edge[j].v;
            if(!vis[v]&&dis[v]>dis[u]+edge[j].w)
              dis[v]=dis[u]+edge[j].w;
        }
    }
}
int main()
{
    n=qread(),m=qread(),s=qread();
    for(int i=1;i<=n;++i)
    dis[i]=0x7fffffff;
    for(int i=1,u,v,w;i<=m;++i)
    {
        u=qread(),v=qread(),w=qread();
        ct(u,v,w);
    }
    dijkstra();
    for(int i=1;i<=n;++i)
    printf("%d ",dis[i]);
    return 0;
}

堆優化dijkstra(O(nlogn)):

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define maxn 200000+1
#define maxn1 100000+1
using namespace std;
struct Edge
{
    int v,nxt,w;
}edge[maxn];
int num,head[maxn],n,m,s,dis[maxn1];
struct node
{
    int x,y;
    bool operator < (const node &a) const
    {
        return y>a.y;
    } 
};
inline void ct(int u,int v,int w)
{
    edge[++num].v=v;
    edge[num].w=w;
    edge[num].nxt=head[u];
    head[u]=num;
}
inline int qread()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) num=num*10+c-‘0‘;
    return num*f;
}
inline void dijkstra()
{
    memset(dis,0x3f,sizeof(dis));
    dis[s]=0;
    priority_queue<node>q;
    q.push((node){s,0});
    while(!q.empty())
    {
        int u=q.top().x,d=q.top().y;
        q.pop();
        if(d!=dis[u]) continue;
        for(int i=head[u];i;i=edge[i].nxt)
        {
            int v=edge[i].v;
            if(dis[v]>dis[u]+edge[i].w)
            {
                dis[v]=dis[u]+edge[i].w;
                q.push((node){v,dis[v]});   
            }   
        }   
    } 
}
int main()
{
    n=qread(),m=qread(),s=qread();
    for(int i=1,u,v,w;i<=m;++i)
    {
        u=qread(),v=qread(),w=qread();
        ct(u,v,w);
    }
    dijkstra();
    for(int i=1;i<=n;++i)
        cout<<dis[i]<<" ";
    return 0;
}

堆:

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n;
int main()
{
    priority_queue<int ,vector<int> ,greater<int > >q;
    scanf("%d",&n);
    while(n--)
    {
        int k;
        scanf("%d",&k);
        if(k==1)
        {
            scanf("%d",&k);
            q.push(k);
        }
        else
          if(k==2)
            printf("%d\n",q.top());
        else
          q.pop();
    }
    return 0;
}

並查集:

#include<iostream>
#include<cstdio>
#define X 10000+10
using namespace std;
int fa[X];
int find(int x)
{
    if(fa[x]!=x) return fa[x]=find(fa[x]);
    return x;
}
void fac(int x,int y)
{
    x=find(x),y=find(y);
    fa[x]=y;
}
bool pd(int x,int y)
{
    if(find(x)==find(y)) return 1;
    return 0;
}
int main()
{
    int n,m,a,b,z;
    cin>>n>>m;
    for(int i=1;i<=n;++i)
    fa[i]=i;
    while(m--)
    {
        cin>>z>>a>>b;
        if(z==1) 
        {
            if(find(a)!=find(b)) 
            fac(a,b);
        } 
        if(z==2)
        {
            if(pd(a,b)==1) cout<<"Y"<<endl;
            else
            cout<<"N"<<endl;
        }
    }
    return 0;
} 

乘法逆元:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define ll long long
using namespace std;
const int maxn=3e6+1;
ll inv[maxn],n,p;
int main()
{
    scanf("%lld%lld",&n,&p);
    inv[1]=1;
    for(int i=2;i<=n;++i)
    {
        inv[i]=(ll)(p-p/i)*inv[p%i]%p;
    }
    for(int i=1;i<=n;++i)
    {
        cout<<inv[i]<<‘\n‘;
    }
    return 0;
}

整理的各種模板 (隨時棄坑emmmmm)