模板

高精

#include<bits/stdc++.h>
using namespace std;
const int N=40005;
struct bign{
    int len,v[N];char s[N];int op;
    bign(){op=1;len=1;memset(v,0,sizeof(v));}
    void in(){
        scanf("%s",s+1);
        int ls=strlen(s+1);len=ls;
        for(int i=1;i<=ls;i++)
            v[i]=s[ls-i+1]-'0';
    }
    void out(){
        bool ok=0;
        if(len==1&&v[1]==0)putchar('0');
        for(int i=len;i>=1;i--)
            if(v[i]!=0||ok){printf("%d",v[i]);ok=1;}puts("");
    }
    void del0(){while(v[len]==0&&len>1)len--;}
    friend bool operator < (bign &A,bign &B){
        A.del0();B.del0();
        if(A.len!=B.len)return A.len<B.len;
        for(int i=A.len;i>=1;i--)
            if(A.v[i]!=B.v[i])return A.v[i]<B.v[i];
        return 0;
    }
    friend bign operator + (const bign &A,const bign &B){
        int mx=max(A.len,B.len);bign C;
        C.len=mx;
        for(int i=1;i<=mx;i++)C.v[i]=A.v[i]+B.v[i];
        for(int i=1;i<=mx;i++)
            if(C.v[i]>9)C.v[i]-=10,C.v[i+1]++;
        if(C.v[mx+1]>0)C.len=mx+1;
        return C;
    }
    friend bign operator * (const bign &A,const bign &B){
        int mx=A.len+B.len+2;bign C;
        for(int i=1;i<=A.len;i++)
            for(int j=1;j<=B.len;j++)
                C.v[i+j-1]+=A.v[i]*B.v[j];
        for(int i=1;i<=mx+2;i++)
            C.v[i+1]+=C.v[i]/10,C.v[i]%=10;
        while(C.v[mx]==0&&mx>1)mx--;
        C.len=mx;
        return C;
    }
    friend void Swap(bign &A,bign &B){bign C;C=A;A=B;B=C;}
    friend bign operator - (bign &A,bign &B){
        bool ok=0;
        if(A<B)Swap(A,B),ok=1;
        bign C;int mx=A.len,flag=0;
        for(int i=1;i<=mx;i++){
            C.v[i]=A.v[i]-B.v[i]-flag;
            if(C.v[i]<0)C.v[i]+=10,C.v[i+1]--,flag=1;
            else flag=0;
        }
        while(C.v[mx]==0&&mx>1)mx--;
        if(ok)Swap(A,B);
        C.len=mx;return C;
    }
}a,b,c;
int main(){
    a.in();b.in();
    c=a+b;c.out();
    return 0;
}
View Code

快读快写 (fread + fwrite A+B problem)

#include<bits/stdc++.h>
using namespace std;
char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int rd(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*f;
}
void write(int x){
    if(x>9)write(x/10);
    *O++=x%10+'0';
}
int main(){
    int a,b;
    a=rd();b=rd();
    write(a+b);fwrite(obuf,O-obuf,1,stdout);
    return 0;
}
View Code

火车头(卡常)

#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
View Code

矩阵乘法 https://www.luogu.com.cn/problem/P1939

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5,mod=1e9+7;
struct mat{
    int n,m,v[N][N];
    mat(){memset(v,n=m=0,sizeof(v));}
    mat operator *(mat b){
        mat c;c.n=n,c.m=b.m;
        for(int i=0;i<c.n;i++)
            for(int j=0;j<c.m;j++)
                for(int k=0;k<m;k++)
                    c.v[i][j]=(1LL*c.v[i][j]+1LL*v[i][k]*b.v[k][j])%mod;
        return c;
    }
};
mat power(mat a,int k){
    mat ans=a;
    for(;k;k>>=1){
        if(k&1)ans=ans*a;
        a=a*a;
    }
    return ans;
}
signed main(){
    int T;
    scanf("%lld",&T);
    while(T--){
        int k;
        scanf("%lld",&k);
        if(k<=3){cout<<1<<endl;continue;}
        k-=2;
        mat a;
        a.n=3;a.m=3;
        a.v[0][0]=1;a.v[0][1]=0;a.v[0][2]=1;
        a.v[1][0]=1;a.v[1][1]=0;a.v[1][2]=0;
        a.v[2][0]=0;a.v[2][1]=1;a.v[2][2]=0;
        mat ans=power(a,k);
        mat f;
        f.n=1;f.m=3;
        f.v[0][0]=1;
        f.v[1][0]=1;
        f.v[2][0]=1;
        f=f*ans;
        printf("%lld\n",f.v[0][0]);
    }
    return 0;
}
View Code

 左偏树 (小根堆) https://www.luogu.com.cn/problem/P3377

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,T;
int rt[N],ls[N],rs[N],dis[N];
bool vis[N];
struct node{
    int id,v;
    bool operator <(node& x)const{return v==x.v?id<x.id:v<x.v;}
}a[N];
int find(int x){return rt[x]==x?x:rt[x]=find(rt[x]);}
int merge(int x,int y){
    if(!x||!y)return x|y;
    if(a[y]<a[x])swap(x,y);
    rs[x]=merge(rs[x],y);
    if(dis[ls[x]]<dis[rs[x]])swap(ls[x],rs[x]);
    dis[x]=dis[rs[x]]+1;
    return x;
}
int del(int x){
    rt[ls[x]]=rt[rs[x]]=rt[x]=merge(ls[x],rs[x]);
    ls[x]=rs[x]=dis[x]=0;
}
int main(){
    dis[0]=-1;
    scanf("%d%d",&n,&T);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i].v);
        a[i].id=i;rt[i]=i;
    }
    while(T--){
        int op,x,y;
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d",&x,&y);
            if(vis[x]||vis[y])continue;
            int fx=find(x),fy=find(y);
            if(fx!=fy)rt[fx]=rt[fy]=merge(fx,fy);
        }
        else{
            scanf("%d",&x);
            if(vis[x]){puts("-1");continue;}
            x=find(x);vis[x]=true;
            printf("%d\n",a[x].v);
            del(x);
        }
    }
    return 0;
}
View Code

 割边 https://www.luogu.com.cn/problem/T103481

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int head[N],nxt[N<<2],to[N<<2];
int n,m,num,tot=1;
int low[N],dfn[N];
bool bridge[N<<2];
void add(int x,int y){
    nxt[++tot]=head[x];
    head[x]=tot;
    to[tot]=y;
}
void tarjan(int u,int ine){
    low[u]=dfn[u]=++num;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(!dfn[v]){
            tarjan(v,i);
            low[u]=min(low[u],low[v]);
            if(dfn[u]<low[v])
                bridge[i]=bridge[i^1]=true;
        }
        else if(i!=(ine^1)) 
            low[u]=min(low[u],dfn[v]);
    }return;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])tarjan(i,0);
    int ans=0;
    for(int i=2;i<tot;i+=2)
        if(bridge[i])ans++;
    cout<<ans;
    return 0;
}
View Code

 割点 https://www.luogu.com.cn/problem/P3388

#include<bits/stdc++.h>
using namespace std;
const int N=2e4+5,M=4e6+5;
int nxt[M],head[N],to[M],cut[N];
int n,m,num,tot;
int low[N],dfn[N],rt=0;
bool vis[N];
void add(int x,int y){
    nxt[++tot]=head[x];
    head[x]=tot;
    to[tot]=y;
}
void tarjan(int u){
    low[u]=dfn[u]=++num;
    int flag=0;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
            if(dfn[u]<=low[v]){
                flag++;
                if(u!=rt||flag>1)cut[u]=true;
            }
        }
        else low[u]=min(low[u],dfn[v]);
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])rt=i,tarjan(i);
    int ans=0;
    for(int i=1;i<=n;i++)
        if(cut[i])ans++;
    printf("%d\n",ans);
    for(int i=1;i<=n;i++)
        if(cut[i])printf("%d ",i);puts("");
    return 0;
}
View Code

 LCA 全家桶 https://www.luogu.com.cn/problem/P3379

/****************离线Tarjan**********************/
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int head[N],nxt[N<<1],to[N<<1],tot;
int vis[N],fa[N],ans[N];
vector<int>qr[N],qrid[N];
int n,m,s;
int find(int x){
    if(fa[x]==x)return x;
    else return fa[x]=find(fa[x]);
} 
void add(int x,int y){
    nxt[++tot]=head[x];
    head[x]=tot;
    to[tot]=y;
}
void addqr(int x,int y,int id){
    qr[x].push_back(y);
    qr[y].push_back(x);
    qrid[x].push_back(id);
    qrid[y].push_back(id);
}
void tarjan(int u){
    vis[u]=1;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(vis[v])continue;
        tarjan(v);
        fa[v]=u;
    }
    for(int i=0;i<qr[u].size();i++){
        int v=qr[u][i],id=qrid[u][i];
        if(vis[v]==2)ans[id]=find(v);
    }
    vis[u]=2;
}
int main(){
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }        
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        addqr(u,v,i);
    }
    tarjan(s);
    for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
    return 0;
}
/***************倍增lca**********************/
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int n,m,s,f[N][40],dep[N],lg[N],T;
int nxt[N<<1],head[N],to[N<<1],tot;
void add(int x,int y){
    nxt[++tot]=head[x];
    head[x]=tot;
    to[tot]=y;
}
void dfs(int u,int fa){
    dep[u]=dep[fa]+1;
    f[u][0]=fa;
    for(int i=1;i<=lg[dep[u]];i++)
        f[u][i]=f[f[u][i-1]][i-1];
    for(int i=head[u];i;i=nxt[i])
        if(to[i]!=fa)dfs(to[i],u);
}
int lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    while(dep[u]>dep[v])
        u=f[u][lg[dep[u]-dep[v]]];
    if(u==v)return u;
    for(int k=lg[dep[u]];k>=0;k--)
        if(f[u][k]!=f[v][k])
            u=f[u][k],v=f[v][k];
    return f[u][0];
}
int main(){
    scanf("%d%d%d",&n,&T,&s);
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    lg[0]=-1;
    for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1;
    dfs(s,0);
    while(T--){
        int a,b;
        scanf("%d%d",&a,&b);
        printf("%d\n",lca(a,b));
    }
    return 0;
}
/*************树剖lca*******************/
void lca(int u,int v){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        u=fa[u];
    }
    return dep[u]<dep[v]?u:v;
}
View Code

 点双连通分量

void tarjan(int u){
    dfn[u]=low[u]=++num;
    sk[++top]=u;
    if(u==rt&&!(now[u])){
        dcc[++Dcnt].push_back(u);
        return;
    }
    int flag=0;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
            if(dfn[u]<=low[v]){
                flag++;
                if(x!=rt||flag>1)cut[u]=true;
                int y;Dcnt++;
                do{
                    y=sk[top--];
                    dcc[Dcnt].push_back(y);
                }while(y!=v);
                dcc[Dcnt].push_back(u);
            }
        }
        else low[u]=min(low[u],dfn[v]);
    }
    return;
}
int main(){
    for(int i=1;i<=n;i++)
        if(!dfn[i]){rt=i;tarjan(i);}
    int ct=Dcnt;
    for(int i=1;i<=n;i++)
        if(cut[i])new_id[i]=++ct;
    for(int i=1;<=Dcnt;i++)
        for(int j=0;j<dcc[i].size();j++){
            int u=dcc[i][j];
            if(cut[u]){
                add_c(i,new_id[u])
                add_c(new_id[u],i);
            }
            else col[u]=i;
        }
    return 0;
}
View Code

 强连通分量

void tarjan(int u){
    vis[sk[++top]=u]=true;
    dfn[u]=low[u]=++num;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        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]){
        int v;cnt++;
        do{
            v=sk[top--];
            vis[v]=false;
            col[v]=cnt;
        }while(u!=v);
    }
}
int main(){
    for(int u=1;u<=n;u++){
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i];
            if(col[u]==col[v])continue;
            in[col[v]]++;out[col[u]]++;
            add_SCC(col[u],col[v]);
        }
    }
}
View Code

KMP https://www.luogu.com.cn/problem/P3375

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5;
int nxt[N];
char a[N],b[N];
int main(){
    scanf("%s\n%s",a+1,b+1);
    int n=strlen(a+1),m=strlen(b+1);
    int j=0;nxt[1]=0;
    for(int i=2;i<=m;i++){
        while(j&&b[i]!=b[j+1])j=nxt[j];
        if(b[j+1]==b[i])j++;
        nxt[i]=j;
    }
    j=0;
    for(int i=1;i<=n;i++){
        while(j&&b[j+1]!=a[i])j=nxt[j];
        if(b[j+1]==a[i])j++;
        if(j==m){printf("%d\n",i-m+1);j=nxt[j];}
    }
    for(int i=1;i<=m;i++)printf("%d ",nxt[i]);
    return 0;
}
View Code

 可持久化trie https://www.luogu.com.cn/problem/P4735

#include<bits/stdc++.h>
using namespace std;
const int N=6e5+5;
int n,T,tot;
int tr[N*24][2],lt[N*24],rt[N*24];
int s[N];
void insert(int i,int k,int p,int q){
    if(k<0){
        lt[q]=i;
        return;
    }
    int c=s[i]>>k&1;
    if(p)tr[q][c^1]=tr[p][c^1];
    tr[q][c]=++tot;
    insert(i,k-1,tr[p][c],tr[q][c]);
    lt[q]=max(lt[tr[q][0]],lt[tr[q][1]]);
}
int query(int p,int val,int k,int lim){
    if(k<0)return s[lt[p]]^val;
    int c=val>>k&1;
    if(lt[tr[p][c^1]]>=lim)return query(tr[p][c^1],val,k-1,lim);
    else return query(tr[p][c],val,k-1,lim);
}
int main(){
    scanf("%d%d",&n,&T);
    lt[0]=-1;
    rt[0]=++tot;
    insert(0,23,0,rt[0]);
    for(int i=1;i<=n;i++){
        int x;scanf("%d",&x);
        s[i]=s[i-1]^x;
        rt[i]=++tot;
        insert(i,23,rt[i-1],rt[i]);
    }
    while(T--){
        char op[3];
        int x,l,r;
        scanf("%s",op);
        if(op[0]=='A'){
            scanf("%d",&x);
            rt[++n]=++tot;
            s[n]=s[n-1]^x;
            insert(n,23,rt[n-1],rt[n]);
        }
        else{
            scanf("%d%d%d",&l,&r,&x);
            printf("%d\n",query(rt[r-1],x^s[n],23,l-1));
        }
    }
    return 0;
}
View Code

 可持久化并查集 https://www.luogu.com.cn/problem/P3402

#include<bits/stdc++.h>
using namespace std;
const int N=3.5e6+5;
int rt[N],dep[N],fa[N],ls[N],rs[N];
int n,T,now,cnt;
void build(int &p,int l,int r){
    p=++cnt;
    if(l==r){fa[p]=l;return;}
    int mid=l+r>>1;
    build(ls[p],l,mid);
    build(rs[p],mid+1,r);
}
void change(int &p,int q,int l,int r,int x,int F){
    p=++cnt;
    if(l==r){
        fa[p]=F;
        dep[p]=dep[q];
        return;
    }
    ls[p]=ls[q];rs[p]=rs[q];
    int mid=l+r>>1;
    if(x<=mid)change(ls[p],ls[q],l,mid,x,F);
    else change(rs[p],rs[q],mid+1,r,x,F);
}
void add(int p,int l,int r,int x){
    if(l==r){++dep[p];return;}
    int mid=l+r>>1;
    if(x<=mid)add(ls[p],l,mid,x);
    else add(rs[p],mid+1,r,x);
}
int query(int p,int l,int r,int x){
    if(l==r)return p;
    int mid=l+r>>1;
    if(x<=mid)return query(ls[p],l,mid,x);
    else return query(rs[p],mid+1,r,x);
}
int find(int x,int RT){
    int F=query(RT,1,n,x);
    if(x==fa[F])return F;
    return find(fa[F],RT);
}
int main(){
    scanf("%d%d",&n,&T);
    build(rt[0],1,n);
    while(T--){
        int op,x,y;
        scanf("%d",&op);
        if(op==1){
            ++now;rt[now]=rt[now-1];
            scanf("%d%d",&x,&y);
            int fx=find(x,rt[now]);
            int fy=find(y,rt[now]);
            if(fa[fx]==fa[fy])continue;
            if(dep[fx]>dep[fy])swap(fx,fy);
            change(rt[now],rt[now-1],1,n,fa[fx],fa[fy]);
            if(dep[fx]==dep[fy])add(rt[now],1,n,fa[fy]);
        }
        else if(op==2){
            ++now;int k;
            scanf("%d",&k);
            rt[now]=rt[k];
        }
        else{
            scanf("%d%d",&x,&y);
            int fx=find(x,rt[now]);
            int fy=find(y,rt[now]);
            if(fa[fx]==fa[fy])puts("1");
            else puts("0");
            now++;rt[now]=rt[now-1];
        }    
    }
    return 0;
}
View Code

 三分 https://www.luogu.com.cn/problem/P3382

#include<bits/stdc++.h>
#define eps (1e-6)
using namespace std;
const int N=15;
int n;double a[N];
double f(double x){
    double ans =0.0;
    for(int i=0;i<=n;i++)ans=ans*x+a[i]; 
    return ans;
}
int main(){
    double l,r;
    scanf("%d",&n);
    cin>>l>>r;
    for(int i=0;i<=n;i++)cin>>a[i];
    while(l+eps<r){
        double lm=l+(r-l)/3.0;
        double rm=r-(r-l)/3.0;
        if(f(lm)>f(rm))r=rm;
        else l=lm;
    }
    printf("%.5lf",l);
    return 0;
}
View Code

 线段树合并 https://www.luogu.com.cn/problem/P4556

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,MX=1e5;
int n,T,cnt,num;
int nxt[N],to[N],head[N],tot;
int siz[N],dep[N],fa[N],son[N];
int dfn[N],rnk[N],top[N];
int rt[N<<5],ls[N<<5],rs[N<<5];
int bh[N<<5],mx[N<<5];
void update(int p){
    if(mx[ls[p]]<mx[rs[p]]){
        mx[p]=mx[rs[p]];
        bh[p]=bh[rs[p]];
    }
    else{
        mx[p]=mx[ls[p]];
        bh[p]=bh[ls[p]];
    }
}
void add(int x,int y){
    nxt[++tot]=head[x];
    head[x]=tot;
    to[tot]=y;
}
void dfspre(int u,int F){
    dep[u]=dep[F]+1;
    siz[u]=1;fa[u]=F;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(v==F)continue;
        dfspre(v,u);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]])
            son[u]=v;
    }
}
void DFS(int u,int t){
    dfn[u]=++cnt;rnk[cnt]=u;top[u]=t;
    if(son[u])DFS(son[u],t);int v;
    for(int i=head[u];i;i=nxt[i])
        if((v=to[i])!=fa[u]&&v!=son[u])DFS(v,v);
}
int lca(int u,int v){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        u=fa[top[u]];
    }
    return dep[u]<dep[v]?u:v;
}

void change(int &p,int l,int r,int x,int k){
    if(!p)p=++num;
    if(l==r){
        mx[p]+=k;
        bh[p]=l;
        return;
    }
    int mid=l+r>>1;
    if(x<=mid)change(ls[p],l,mid,x,k);
    else change(rs[p],mid+1,r,x,k);
    update(p); 
}
int merge(int p,int q,int l,int r){
    if(!p||!q)return p|q;
    if(l==r){
        mx[p]+=mx[q];
        bh[p]=mx[p]?l:0;
        return p;
    }
    int mid=l+r>>1;
    ls[p]=merge(ls[p],ls[q],l,mid);
    rs[p]=merge(rs[p],rs[q],mid+1,r);
    update(p);
    return p;
}
void dfs(int u){
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(v==fa[u])continue;
        dfs(v);
        rt[u]=merge(rt[u],rt[v],1,MX);
    }
}
int main(){
    scanf("%d%d",&n,&T);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    for(int i=1;i<=n;i++)rt[i]=++num;
    dfspre(1,0);
    DFS(1,1);
    while(T--){
        int u,v,z;
        scanf("%d%d%d",&u,&v,&z);
        int acc=lca(u,v);
        change(rt[u],1,MX,z,1);
        change(rt[v],1,MX,z,1);
        change(rt[acc],1,MX,z,-1);
        if(fa[acc])change(rt[fa[acc]],1,MX,z,-1);
    }
    dfs(1);
    for(int i=1;i<=n;i++)
        printf("%d\n",bh[rt[i]]);
    return 0;
}
View Code

 st表 https://www.luogu.com.cn/problem/P3865

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,T,a[N],lg[N];
int f[N][17];
int main(){
    scanf("%d%d",&n,&T);
    lg[0]=-1;
    for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        f[i][0]=a[i]; 
    }
    int t=lg[n];
    for(int j=1;j<=t;j++)
        for(int i=1;i<=n-(1<<j)+1;i++)
            f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    while(T--){
        int l,r;
        scanf("%d%d",&l,&r);
        int k=lg[r-l+1];
        printf("%d\n",max(f[l][k],f[r-(1<<k)+1][k])); 
    }
    return 0;
}
View Code

 点分治 https://www.luogu.com.cn/problem/P3806

#include<bits/stdc++.h>
#define inf (1<<30)
using namespace std;
const int N=2e5+10;
int n,T,cnt,ns,rt;
int nxt[N],head[N],to[N],val[N],tot;
int me[N],siz[N],Q[N]; 
bool vis[N],can[N];
struct Node{
    int t,d,bl;
}a[N];
void add(int x,int y,int z){
    nxt[++tot]=head[x];
    head[x]=tot;to[tot]=y;
    val[tot]=z;
}
void findrt(int u,int F){
    me[u]=0;siz[u]=1;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(v==F||vis[v])continue;
        findrt(v,u); 
        siz[u]+=siz[v];
        me[u]=max(me[u],siz[v]);
    }
    me[u]=max(me[u],ns-siz[u]);
    if(me[u]<me[rt])rt=u;
}
void DFS(int u,int F,int dis,int col){
    ++cnt;
    a[cnt].t=u;
    a[cnt].d=dis;
    a[cnt].bl=col;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i],z=val[i];
        if(vis[v]||v==F)continue;
        DFS(v,u,dis+z,col);
    }
}
bool cmp(Node A,Node B){
    if(A.d!=B.d)return A.d<B.d;
}
void solve(int u){
    cnt=0;
    ++cnt;
    a[cnt].t=u;
    a[cnt].d=0;
    a[cnt].bl=u;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i],z=val[i];
        if(vis[v])continue;
        DFS(v,u,z,v);
    }
    sort(a+1,a+cnt+1,cmp);
    for(int i=1;i<=T;i++){
        int l=1,r=cnt;
        while(l<r){
            if(a[l].d+a[r].d>Q[i])r--;
            else if(a[l].d+a[r].d<Q[i])l++;
            else if(a[r].bl==a[l].bl){
                if(a[r].bl==a[r-1].bl)r--;
                else l++;
            }
            else{
                can[i]=true;
                break;
            }
        }
    }
    return; 
}
void dfs(int u){
    vis[u]=true;
    solve(u);
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(vis[v])continue;
        ns=siz[v];rt=0;
        findrt(v,0);
        dfs(rt);
    }
}
int main(){
    scanf("%d%d",&n,&T);
    for(int i=1;i<n;i++){
        int u,v,l;
        scanf("%d%d%d",&u,&v,&l);
        add(u,v,l);add(v,u,l);
    }
    for(int i=1;i<=T;i++)
        scanf("%d",&Q[i]);
    ns=n;me[0]=inf;rt=0;
    findrt(1,0);
    dfs(rt);
    for(int i=1;i<=T;i++)
        puts(can[i]?"AYE":"NAY");
    return 0;
}
View Code

 Dijkstra https://www.luogu.com.cn/problem/P4779

#include<bits/stdc++.h>
#define ll long long
#define mkr make_pair
using namespace std;
const int N=4e5+10;
int head[N],to[N],val[N],nxt[N];
int tot,n,m,st,d[N];bool v[N];
priority_queue< pair<int,int> >q;
void add(int x,int y,int z){
    nxt[++tot]=head[x];
    to[tot]=y;val[tot]=z;
    head[x]=tot;
}
void dijkstra(int st){
    memset(d,0x3f,sizeof(d));
    memset(v,0,sizeof(v));
    d[st]=0;q.push(mkr(0,st));
    while(q.size()){
        int u=q.top().second;q.pop();
        if(v[u])continue;v[u]=true;
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i],z=val[i];
            if(d[v]>d[u]+z){
                d[v]=d[u]+z;
                q.push(mkr(-d[v],v));
            }
        }
    }
}
int main(){
    scanf("%d%d%d",&n,&m,&st);
    for(int i=1,u,v,l;i<=m;i++){
        scanf("%d%d%d",&u,&v,&l);
        add(u,v,l);
    }
    dijkstra(st);
    for(int i=1;i<=n;i++)
        if(d[i]!=0x3f3f3f3f)printf("%d ",d[i]);
        else printf("%lld ",(1LL<<32)-1);
    return 0;
}
View Code

差分约束 spfa 负环 https://www.luogu.com.cn/problem/P5960

#include<bits/stdc++.h>
#define inf (0x3f3f3f3f)
using namespace std;
const int N=2e4+10;
int n,m;
int nxt[N],head[N],to[N],val[N],tot;
bool vis[N];
int dis[N],cnt[N];
queue<int>q;
void add(int x,int y,int z){
    nxt[++tot]=head[x];
    head[x]=tot;to[tot]=y;
    val[tot]=z;
}
bool spfa(int st){
    for(int i=0;i<=n;i++)
        dis[i]=inf,vis[i]=0,cnt[i]=0;
    dis[st]=0;vis[st]=true,q.push(st);
    while(q.size()){
        int u=q.front();q.pop();
        vis[u]=false;
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i],z=val[i];
            if(dis[v]>dis[u]+z){
                dis[v]=dis[u]+z;
                cnt[v]=cnt[u]+1;
                if(cnt[u]>=n)return false;
                if(!vis[v]){
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
    }
    return true;
}
void print(){
    for(int i=1;i<=n;i++)
        printf("%d ",dis[i]);
    return;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(v,u,w);
    }    
    for(int i=1;i<=n;i++)
        add(0,i,0);
    int flag=spfa(0);
    if(!flag)puts("NO");
    else print();
    return 0;
}
View Code

 后缀数组 SA https://www.luogu.com.cn/problem/P3809

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m;
char s[N];
int rk[N<<1],oldrk[N<<1],sa[N],id[N],cnt[N];
int px[N],ht[N];
bool cmp(int x,int y,int w){
  return oldrk[x]==oldrk[y]&&oldrk[x+w]==oldrk[y+w];
}
int main(){
    int p;
    scanf("%s",s+1);
    n=strlen(s+1);
    m=max(n,300);
    for(int i=1;i<=n;i++)++cnt[rk[i]=s[i]];
    for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
    for(int i=n;i>=1;--i)sa[cnt[rk[i]]--]=i;
    for(int w=1;;w<<=1,m=p){
        p=0;
        for(int i=n;i>n-w;i--)id[++p]=i;
        for(int i=1;i<=n;i++)if(sa[i]>w)id[++p]=sa[i]-w;
        for(int i=1;i<=m;i++)cnt[i]=0;
        for(int i=1;i<=n;i++)++cnt[px[i]=rk[id[i]]];
        for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
        for(int i=n;i>=1;i--)sa[cnt[px[i]]--]=id[i];
        memcpy(oldrk,rk,sizeof(oldrk));
        p=0;
        for(int i=1;i<=n;i++)
            rk[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;
        if(p==n){
            for(int i=1;i<=n;i++)sa[rk[i]]=i;
            break;
        }
    }
    for(int i=1,k=0;i<=n;i++){
        if(k)--k;
        while(s[i+k]==s[sa[rk[i]-1]+k])++k;
        ht[rk[i]]=k;
    }
    for(int i=1;i<=n;i++)printf("%d ",sa[i]);
    puts("");
    for(int i=1;i<=n;i++)printf("%d ",ht[i]);
    puts("");
    for(int i=1;i<=n;i++)printf("%d ",rk[i]);
    return 0;
}
View Code

 prim 最小生成树 https://www.luogu.com.cn/problem/P3366

#include<bits/stdc++.h>
using namespace std;
const int N=5e3+10;
int a[N][N],d[N];
bool v[N];
int prim(int n){
    memset(d,0x3f,sizeof(d));
    d[1]=0;
    int ans=0;
    for(int i=1;i<n;i++){
        int x=0;
        for(int j=1;j<=n;j++)
            if(!v[j]&&(x==0||d[j]<d[x]))x=j;
        v[x]=1;
        for(int j=1;j<=n;j++)
            if(!v[j])d[j]=min(d[j],a[x][j]);
    }
    for(int i=1;i<=n;i++)
        ans+=d[i];
    return ans;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    memset(a,0x3f,sizeof(a)); 
    for(int i=1;i<=m;i++){
        int u,v,l;
        scanf("%d%d%d",&u,&v,&l);
        a[u][v]=a[v][u]=min(a[u][v],l);
    }
    printf("%d",prim(n));
    return 0;
}
View Code

kruskal 最小生成树 https://www.luogu.com.cn/problem/P3366

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,m,fa[N],ans;
struct edge{
    int u,v,w;
}a[N];
bool cmp(edge x,edge y){
    return x.w<y.w;
}
int find(int x){
    if(fa[x]!=x)return fa[x]=find(fa[x]);
    return x;
}
long long kruskal(){
    long long ans=0;
    for(int i=1;i<=m;i++){
        int x=a[i].u;
        int y=a[i].v;
        int fx=find(x);
        int fy=find(y);
        if(fx!=fy)fa[fx]=fy,ans+=a[i].w;
    }
    return ans;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        fa[i]=i;
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
    sort(a+1,a+m+1,cmp);
    printf("%lld",kruskal());
    return 0;
}
View Code

 dinic https://www.luogu.com.cn/problem/P3376

#include<bits/stdc++.h>
#define inf (0x3f3f3f3f)
#define ll long long
using namespace std;
const int N=205,M=2e4+10;
int n,m,s,t;
int nxt[M],to[M],edge[M],head[M],tot=1;
int d[N],cur[N];
queue<int>q;
void add(int x,int y,int z){
    nxt[++tot]=head[x];
    to[tot]=y;
    head[x]=tot;
    edge[tot]=z;
}
bool bfs(){
    memset(d,-1,sizeof(d));
    while(q.size())q.pop();
    q.push(s);d[s]=0;
    cur[s]=head[s];
    while(q.size()){
        int u=q.front(),v;q.pop();
        for(int i=head[u];i;i=nxt[i])
            if(d[v=to[i]]==-1&&edge[i]){
                q.push(v);
                d[v]=d[u]+1;
                cur[v]=head[v];
                if(v==t)return true;
            }
    }
    return false;
}
ll dfs(int u,ll lim){
    if(u==t)return lim;
    ll flow=0;
    for(int i=cur[u];i&&flow<lim;i=nxt[i]){
        cur[u]=i;
        int v=to[i];
        if(edge[i]!=0&&d[v]==d[u]+1){
            ll k=dfs(v,min(1LL*edge[i],lim-flow));
            if(!k)d[v]=-1;
            edge[i]-=k;
            edge[i^1]+=k;
            flow+=k;
        }
    }
    return flow;
}
ll dinic(){
    ll flow=0,maxflow=0;
    while(bfs())
        while(flow=dfs(s,inf))
            maxflow+=flow;
    return maxflow;
}
signed main(){
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++){
        int u,v,l;
        scanf("%d%d%d",&u,&v,&l);
        add(u,v,l);
        add(v,u,0);
    }
    printf("%lld",dinic());
    return 0; 
}
View Code

EK https://loj.ac/p/101

#include<bits/stdc++.h>
#define inf (0x3f3f3f3f)
#define int long long
using namespace std;
const int N=205,M=2e4+10;
int n,m,s,t,maxflow;
int pre[M],to[M],now[N],val[M],tot=1;
int pr[M],incf[N];
bool vis[N];
void add(int x,int y,int z){
    pre[++tot]=now[x];now[x]=tot;to[tot]=y;val[tot]=z;
    pre[++tot]=now[y];now[y]=tot;to[tot]=x;val[tot]=0;
}
bool bfs(){
    memset(vis,0,sizeof(vis));
    queue<int>q;
    q.push(s);vis[s]=true;
    incf[s]=inf;
    while(q.size()){
        int u=q.front(),v;q.pop();
        for(int i=now[u];i;i=pre[i])
            if(val[i]&&!vis[to[i]]){
                v=to[i];
                vis[v]=true;
                incf[v]=min(incf[u],val[i]);
                pr[v]=i;
                q.push(v);
                if(v==t)return true;
            }
    }
    return false;
}
void update(){
    int u=t;
    while(u!=s){
        int i=pr[u];
        val[i]-=incf[t];
        val[i^1]+=incf[t];
        u=to[i^1];
    }
    maxflow+=incf[t];
}
signed main(){
    scanf("%lld%lld%lld%lld",&n,&m,&s,&t);    
    for(int i=1;i<=m;i++){
        int u,v,l;
        scanf("%lld%lld%lld",&u,&v,&l);
        add(u,v,l);
    }
    while(bfs())update();
    printf("%lld",maxflow);
    return 0;
}
View Code

 决策单调性(玩具装箱) https://www.luogu.com.cn/problem/P3195

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=5e4+10;
int n,L,c[N];
long long f[N],sum[N];
struct Stack{
    int l,r,x;
    Stack(){}
    Stack(int LL,int RR,int XX){l=LL;r=RR;x=XX;}
};
Stack sk[N];int top=0;
long long W(int i,int j){
    int now=sum[j]-sum[i-1]-L;
    return 1LL*(j-i+now)*(j-i+now);
}
int find(int id,int l,int r){
    while(l<=r){
        int mid=l+r>>1;
        if(f[id]+W(id+1,mid)<f[sk[top].x]+W(sk[top].x+1,mid))r=mid-1;
        else l=mid+1;
    }
    return l;
}
int main(){
    scanf("%d%d",&n,&L);
    for(int i=1;i<=n;i++){
        scanf("%d",&c[i]);
        sum[i]=sum[i-1]+c[i];
    }
    int now=1;top=1;
    sk[top]=Stack(1,n,0);
    for(int i=1;i<=n;i++){
        f[i]=f[sk[now].x]+W(sk[now].x+1,i);
        while(i<sk[top].l&&f[i]+W(i+1,sk[top].l)<f[sk[top].x]+W(sk[top].x+1,sk[top].l))
            --top;
        int u=find(i,sk[top].l,sk[top].r);
        sk[top].r=u-1;
        if(u<=n)sk[++top]=Stack(u,n,i);
        if(i==sk[now].r)now++;
    }
    printf("%lld",f[n]);
    return 0;
}
View Code

 最长上升子序列 LIS 

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,ans,a[N],f[N];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++){
        int x=lower_bound(f,f+ans+1,a[i])-f;
        f[x]=a[i];
        if(ans<x)ans=x;
    }
    cout<<ans;
    return 0;
}
View Code

 动态开点 https://www.luogu.com.cn/problem/P1908

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int n,rt=0,cnt=0;
int sum[N<<5],ls[N<<5],rs[N<<5];
void update(int p){
    sum[p]=sum[ls[p]]+sum[rs[p]];
}
int query(int p,int l,int r,int x,int y){
    if(!p)return 0;
    if(l==x&&r==y)return sum[p];
    int mid=l+r>>1;
    if(y<=mid)return query(ls[p],l,mid,x,y);
    if(x>mid)return query(rs[p],mid+1,r,x,y);
    return query(ls[p],l,mid,x,mid)+query(rs[p],mid+1,r,mid+1,y);
}
void change(int &p,int l,int r,int x,int k){
    if(!p)p=++cnt;
    if(l==r){
        sum[p]+=k;
        return;
    }
    int mid=l+r>>1;
    if(x<=mid)change(ls[p],l,mid,x,k);
    else change(rs[p],mid+1,r,x,k);
    update(p);
}
int main(){
    scanf("%d",&n);
    long long ans=0;
    for(int i=1;i<=n;i++){
        int x;
        scanf("%d",&x);
        ans+=query(rt,1,1e9,x+1,1e9);
        change(rt,1,1e9,x,1);
    }
    printf("%lld\n",ans);    
    return 0;
}
View Code

 单调栈 https://www.luogu.com.cn/problem/P5788

#include<bits/stdc++.h>
using namespace std;
const int N=3e6+10;
int n,a[N],f[N];
int sk[N],top;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    f[n]=0;sk[++top]=n;
    for(int i=n-1;i>=1;i--){
        while(a[i]>=a[sk[top]]&&top)top--;
        f[i]=sk[top];
        sk[++top]=i;
    }
    for(int i=1;i<=n;i++)
        printf("%d ",f[i]);
    return 0;
}
View Code

单调队列 https://www.luogu.com.cn/problem/P1886

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,k,a[N],q[N];
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int l=1,r=0;
    for(int i=1;i<=n;i++){
        while(l<=r&&a[i]<a[q[r]])r--;
        q[++r]=i;
        while(l<=r&&i-q[l]>=k)l++;
        if(i>=k)printf("%d ",a[q[l]]);
    }puts("");
    l=1,r=0;
    for(int i=1;i<=n;i++){
        while(l<=r&&a[i]>a[q[r]])r--;
        q[++r]=i;
        while(l<=r&&i-q[l]>=k)l++;
        if(i>=k)printf("%d ",a[q[l]]);
    }
    return 0;
}
View Code

 树链剖分 重链剖分 https://www.luogu.com.cn/problem/P3384

#include<bits/stdc++.h>
#define int long long
#define ls p<<1
#define rs p<<1|1
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r 
using namespace std;
const int N=1e6+5,M=1e6+5;
int n,T,rt,P,cnt;
int sum[N],tag[N];
int head[N],nxt[M],to[M],tot;
int a[N];
int fa[N],siz[N],dep[N],son[N];
int top[N],dfn[N],rnk[N];
void update(int p){
    sum[p]=(sum[ls]+sum[rs])%P;
}
void pushdown(int p,int l,int r){
    if(!tag[p])return;
    int mid=l+r>>1;
    tag[ls]+=tag[p];tag[ls]%=P;
    tag[rs]+=tag[p];tag[rs]%=P;
    sum[ls]+=tag[p]*(mid-l+1);sum[ls]%=P;
    sum[rs]+=tag[p]*(r-mid);sum[rs]%=P;
    tag[p]=0;
}
void add(int u,int v){
    nxt[++tot]=head[u];
    to[tot]=v;
    head[u]=tot;
}
void dfspre(int u,int F){
    dep[u]=dep[F]+1;
    siz[u]=1;fa[u]=F;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(v==F)continue;
        dfspre(v,u);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[v]])son[u]=v;
    }
}
void DFS(int u,int t){
    dfn[u]=++cnt;rnk[cnt]=u;top[u]=t;
    if(son[u])DFS(son[u],t);int v;
    for(int i=head[u];i;i=nxt[i])
        if((v=to[i])!=son[u]&&v!=fa[u])DFS(v,v);
}
void build(int p,int l,int r){
    if(l==r){
        sum[p]=a[rnk[l]]%P;
        return;
    }
    int mid=l+r>>1;
    build(lson);build(rson);
    update(p);
}
int trsum(int p,int l,int r,int x,int y){
    if(x<=l&&y>=r)return sum[p]%P;
    int ret=0,mid=l+r>>1;
    pushdown(p,l,r);
    if(x<=mid)ret=(ret+trsum(lson,x,y))%P;
    if(y>mid)ret=(ret+trsum(rson,x,y))%P;
    return ret;
}
void trchange(int p,int l,int r,int x,int y,int v){
    if(x<=l&&y>=r){
        tag[p]+=v;tag[p]%=P;
        sum[p]+=(r-l+1)*v;sum[p]%=P;
        return;
    }
    pushdown(p,l,r);
    int mid=l+r>>1;
    if(x<=mid)trchange(lson,x,y,v);
    if(y>mid)trchange(rson,x,y,v);
    update(p);
}
void change(int u,int v,int k){
    k%=P;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        trchange(1,1,n,dfn[top[u]],dfn[u],k);
        u=fa[top[u]];
    }
    if(dep[u]>dep[v])swap(u,v);
    trchange(1,1,n,dfn[u],dfn[v],k);
}
int query(int u,int v){
    int ret=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        ret+=trsum(1,1,n,dfn[top[u]],dfn[u]);ret%=P;
        u=fa[top[u]];
    }
    if(dep[u]>dep[v])swap(u,v);
    ret+=trsum(1,1,n,dfn[u],dfn[v]);ret%=P;
    return ret;
}
signed main(){
    scanf("%lld%lld%lld%lld",&n,&T,&rt,&P);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%lld%lld",&u,&v);
        add(u,v);add(v,u);
    }
    dfspre(rt,0);
    DFS(rt,rt);
    build(1,1,n);
    while(T--){
        int op,x,y,v;
        scanf("%lld",&op);
        if(op==1){
            scanf("%lld%lld%lld",&x,&y,&v);
            change(x,y,v);
        }
        else if(op==2){
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",query(x,y));
        }
        else if(op==3){
            scanf("%lld%lld",&x,&v);
            trchange(1,1,n,dfn[x],dfn[x]+siz[x]-1,v);
        }
        else{
            scanf("%lld",&x);
            printf("%lld\n",trsum(1,1,n,dfn[x],dfn[x]+siz[x]-1));
        }
    }
    return 0;
}
View Code

 Splay https://www.luogu.com.cn/problem/P3369

#include<bits/stdc++.h>
#define inf (1e9)
using namespace std;
const int N=5e5+5;
struct splay_tree{
    int rt,sz=0;
    int ch[N][2],f[N],siz[N],cnt[N],val[N];
    void clear(int u){ch[u][0]=ch[u][1]=siz[u]=cnt[u]=val[u]=0;}
    int get(int u){return ch[f[u]][1]==u;}
    void update(int u){
        if(u){
            siz[u]=cnt[u];
            if(ch[u][0])siz[u]+=siz[ch[u][0]];
            if(ch[u][1])siz[u]+=siz[ch[u][1]];
        }
    }
    void rotate(int u){
        int fa=f[u],gf=f[fa],wh=get(u);
        ch[fa][wh]=ch[u][wh^1];
        f[ch[fa][wh]]=fa;ch[u][wh^1]=fa;
        f[fa]=u;f[u]=gf;
        if(gf)ch[gf][ch[gf][1]==fa]=u;
        update(fa);update(u);
    }
    void splay(int u,int goal){
        for(int fa;(fa=f[u])!=goal;rotate(u))
            if(f[fa]!=goal)rotate(get(fa)==get(u)?fa:u);
        if(!goal)rt=u;
    }
    int search(int u,int x){
        while(val[u]!=x){
            if(val[u]>x)if(ch[u][0])u=ch[u][0];
            else break;
            if(val[u]<x)if(ch[u][1])u=ch[u][1];
            else break;
        }return u;
    }
    void ins(int x){
        if(rt==0){
            sz++;ch[sz][0]=ch[sz][1]=f[sz]=0;
            rt=sz;siz[sz]=cnt[sz]=1;val[sz]=x;
            return;
        }
        int u=search(rt,x);
        if(val[u]==x){
            cnt[u]++;
            splay(u,0);
            return;
        }
        val[++sz]=x;cnt[sz]=1;f[sz]=u;
        ch[u][x>val[u]]=sz;
        splay(sz,0);
    }
    int kth(int x){
        int u=rt;
        while(true)
        if(ch[u][0]&&x<=siz[ch[u][0]])u=ch[u][0];
        else{
            int tmp=(ch[u][0]?siz[ch[u][0]]:0)+cnt[u];
            if(x<=tmp)return val[u];
            x-=tmp;u=ch[u][1];
        }
    }
    int rnk(int x){
        int u=search(rt,x);
        splay(u,0);
        if(val[u]>=x)return siz[ch[u][0]]+1;
        else return siz[ch[u][0]]+cnt[u]+1; 
    }
    int gmost(int u,int op){
        if(!op)return search(u,-inf);
        else return search(u,inf);
    }
    int pre_nxt(int x,int op){
        int u=search(rt,x);
        splay(u,0);
        if((val[u]<x&&!op)||(val[u]>x&&op))return u;
        else return gmost(ch[u][op],op^1);
    }
    int pre(int x){return val[pre_nxt(x,0)];}
    int nxt(int x){return val[pre_nxt(x,1)];}
    void del(int x){
        int u=search(rt,x);
        if(val[u]!=x)return;
        splay(u,0);
        if(--cnt[u])return;
        if(!ch[u][0]){
            f[ch[u][1]]=0;
            rt=ch[u][1];
            clear(u);
        }else{
            f[ch[u][0]]=0;
            splay(gmost(ch[u][0],1),0);
            ch[rt][1]=ch[u][1];
            siz[rt]+=siz[ch[u][1]];
            if(ch[rt][1])f[ch[rt][1]]=rt;
            clear(u);
        }
    }
}tree;
int main(){
    int T;scanf("%d",&T);
    while(T--){
        int op,x;
        scanf("%d%d",&op,&x);
        if(op==1)tree.ins(x);
        if(op==2)tree.del(x);
        if(op==3)printf("%d\n",tree.rnk(x));
        if(op==4)printf("%d\n",tree.kth(x));
        if(op==5)printf("%d\n",tree.pre(x));
        if(op==6)printf("%d\n",tree.nxt(x));
    }
    return 0;
}
View Code

fhq treap 无旋 https://www.luogu.com.cn/problem/P3369

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int rt,T,cnt;
int val[N],siz[N],ls[N],rs[N],pfer[N];
void updata(int p){if(p)siz[p]=siz[ls[p]]+siz[rs[p]]+1;}
int New(int x){
   int p=++cnt;
   val[p]=x;siz[p]=1;
   ls[p]=rs[p]=0;
   pfer[p]=rand();
   return p;
}
void split(int p,int k,int &x,int &y){
   if(!p){x=y=0;return;}
   if(val[p]<=k){x=p;split(rs[p],k,rs[p],y);}
   else{y=p;split(ls[p],k,x,ls[p]);}
   updata(p);
}
int merge(int x,int y){
   if(!x||!y)return x+y;
   if(pfer[x]>pfer[y]){rs[x]=merge(rs[x],y);updata(x);return x; }
   else{ls[y]=merge(x,ls[y]);updata(y);return y;}
}
void ins(int k){
   int x,y;
   split(rt,k-1,x,y);
   rt=merge(merge(x,New(k)),y);
}
void del(int k){
   int x,y,z;
   split(rt,k,x,z);
   split(x,k-1,x,y);
   if(y)y=merge(ls[y],rs[y]);
   rt=merge(merge(x,y),z);
}
int Rank(int k){
   int x,y,ans;
   split(rt,k-1,x,y);
   ans=siz[x]+1;
   rt=merge(x,y);
   return ans; 
}
int kth(int k){
   int p=rt;
   while(true){
      if(siz[ls[p]]+1==k)break;
      else if(siz[ls[p]]+1>k)p=ls[p];
      else k-=siz[ls[p]]+1,p=rs[p]; 
   }
   return val[p];
}
int pre(int k){
   int x,y,ans,p;
   split(rt,k-1,x,y);
   p=x;
   while(rs[p])p=rs[p];
   ans=val[p];
   rt=merge(x,y);
   return ans;
}
int nxt(int k){
   int x,y,ans,p;
   split(rt,k,x,y);
   p=y;
   while(ls[p])p=ls[p];
   ans=val[p];
   rt=merge(x,y);
   return ans;
}
int main(){
   srand((unsigned int)time(NULL));
   scanf("%d",&T);
   while(T--){
      int op,x;
      scanf("%d%d",&op,&x);
      if(op==1)ins(x);
      if(op==2)del(x);
      if(op==3)printf("%d\n",Rank(x));
      if(op==4)printf("%d\n",kth(x));
      if(op==5)printf("%d\n",pre(x));
      if(op==6)printf("%d\n",nxt(x));
   }
   return 0;
}
View Code

 最小表示法 https://www.luogu.com.cn/problem/P1368

#include<bits/stdc++.h>
using namespace std;
const int N=6e6+5;
int s[N];int n;
int doit(){
    for(int i=1;i<=n;i++)s[i+n]=s[i];
    int k=0,i=1,j=2;
    while(i<=n&&j<=n){
        for(k=0;k<n&&s[i+k]==s[j+k];k++);
        if(k==n)break;
        if(s[i+k]>s[j+k]){i=i+k+1;if(i==j)i++;}
        else{j=j+k+1;if(i==j)j++;}
    }
    int st=min(i,j);return st;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&s[i]);
    int st=doit();
    for(int i=st;i<=st+n-1;i++)printf("%d ",s[i]);
    return 0;
}
View Code

 manacher

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
char d[N<<1];
int p[N<<1],cnt,ans;
void qr(){
    char c=getchar();
    if(c=='E')exit(0);
    d[0]='~',d[cnt=1]='|';
    while(c<'a'||c>'z')c=getchar();
    while(c>='a'&&c<='z')d[++cnt]=c,d[++cnt]='|',c=getchar();
}
int main(){
    int num=0;
    while(true){
        memset(p,0,sizeof(p));
        qr();ans=0;
        for(int i=1,r=0,mid=0;i<=cnt;i++){
            if(i<=r)p[i]=min(p[(mid<<1)-i],r-i+1);
            while(d[i-p[i]]==d[i+p[i]])++p[i];
            if(p[i]+i>r)r=p[i]+i-1,mid=i;
            ans=max(ans,p[i]);
        }
        printf("Case %d: %d\n",++num,ans-1);
    }
    return 0;
}
View Code

 扫描线 https://www.luogu.com.cn/problem/P5490

#include<bits/stdc++.h>
#define int long long
#define x1 nmsl
#define x2 NMSL
#define y1 wcnm
#define y2 wtnm
#define ls p<<1
#define rs p<<1|1
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
using namespace std;
const int N=8e5+5;
int n,c[N],tot;
int wz[N],MX=0;
struct seg{
    int x,y1,y2,op;
    seg(){}
    seg(int X,int Y1,int Y2,int OP){
        x=X;y1=Y1,y2=Y2,op=OP;
    }
}a[N];
int cnt[N<<2],len[N<<2];
bool cmp(seg A,seg B){
    return A.x<B.x;
}
void update(int p,int l,int r){
    if(l==MX&&r==MX)return;
    if(cnt[p])len[p]=wz[r+1]-wz[l];
    else len[p]=len[ls]+len[rs];
}
void change(int p,int l,int r,int x,int y,int v){
    if(x<=l&&y>=r){
        cnt[p]+=v;
        update(p,l,r);
        return;
    }
    int mid=l+r>>1;
    if(x<=mid)change(lson,x,y,v);
    if(y>mid)change(rson,x,y,v);
    update(p,l,r);
}
signed main(){
    scanf("%lld",&n);    
    for(int i=1;i<=n;i++){
        int x1,x2,y1,y2;
        scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
        a[++tot]=seg{x1,y1,y2,1};c[tot]=y1;
        a[++tot]=seg{x2,y1,y2,-1};c[tot]=y2;
    }
    sort(c+1,c+tot+1);
    int m=unique(c+1,c+tot+1)-(c+1);
    for(int i=1;i<=tot;i++){
        int p1=lower_bound(c+1,c+m+1,a[i].y1)-c;
        int p2=lower_bound(c+1,c+m+1,a[i].y2)-c;
        wz[p1]=a[i].y1;
        wz[p2]=a[i].y2;
        a[i].y1=p1;
        a[i].y2=p2;
        MX=max(MX,p2);
    }
    sort(a+1,a+tot+1,cmp);
    long long ans=0;
    for(int i=1;i<tot;i++){
        change(1,1,tot,a[i].y1,a[i].y2-1,a[i].op);
        ans+=len[1]*(a[i+1].x-a[i].x);
    }
    cout<<ans;
    return 0;
}
View Code

 高斯-约旦消元法 https://www.luogu.com.cn/problem/solution/P3389

#include<bits/stdc++.h>
using namespace std;
const int N=105;
int n;double a[N][N];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n+1;j++)
            scanf("%lf",&a[i][j]);
    for(int i=1;i<=n;i++){
        int mx=i;
        for(int j=i+1;j<=n;j++)
            if(abs(a[j][i])>abs(a[mx][i]))mx=j;
        for(int j=1;j<=n+1;j++)swap(a[i][j],a[mx][j]);
        if(!a[i][i])return puts("No Solution")&0;
        for(int j=1;j<=n;j++)if(i!=j){
            double tmp=a[j][i]/a[i][i];
            for(int k=i+1;k<=n+1;k++)a[j][k]-=a[i][k]*tmp;
        }
    }
    for(int i=1;i<=n;i++)printf("%.2lf\n",a[i][n+1]/a[i][i]);
    return 0;
}
View Code

 普通高斯消元 https://www.luogu.com.cn/problem/solution/P2455

#include<bits/stdc++.h>
using namespace std;
const int N=53;
int n;
double a[N][N];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n+1;j++)
            scanf("%lf",&a[i][j]);
    int pl=1;
    for(int k=1;k<=n;k++){
        int mx=pl;
        for(int i=pl+1;i<=n;i++)
            if(abs(a[i][k])>abs(a[mx][k]))mx=i;
        if(a[mx][k]==0)continue;
        for(int j=1;j<=n+1;j++)swap(a[pl][j],a[mx][j]);
        for(int i=1;i<=n;i++){
            if(i==pl)continue;
            double mul=a[i][k]/a[pl][k];
            for(int j=k+1;j<=n+1;j++)
                a[i][j]-=a[pl][j]*mul;            
        }
        ++pl;
    }
    if(pl<=n){
        while(pl<=n)
            if(a[pl++][n+1]!=0)return puts("-1")&0;
        return puts("0")&0;
    }
    for(int i=1;i<=n;i++){
        printf("x%d=",i);
        if((int(a[i][n+1]/a[i][i]*100))==0)puts("0.00");
        else printf("%.2f\n",a[i][n+1]/a[i][i]);
    } 
    return 0;
}
View Code

 树套树 线段树套平衡树 https://www.luogu.com.cn/problem/P3380

#include<bits/stdc++.h>
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define inf (2147483647)
using namespace std;
const int N=1.5e6+5;
int n,T,cnt,Ans,num;
int rt[N],ls[N],rs[N],a[N];
int siz[N],val[N],pfer[N];
void update(int p){
    if(!p)return;
    siz[p]=siz[ls[p]]+siz[rs[p]]+1;
}
int New(int x){
    int p=++cnt;
    val[p]=x;siz[p]=1;
    ls[p]=rs[p]=0;
    pfer[p]=rand()*rand();
    return p;
}
void split(int p,int k,int &x,int &y){
    if(!p){x=y=0;return;}
    if(val[p]<=k){x=p;split(rs[p],k,rs[p],y);}
    else {y=p;split(ls[p],k,x,ls[p]);}
    update(p);
}
int merge(int x,int y){
    if(!x||!y)return x|y;
    if(pfer[x]>pfer[y]){rs[x]=merge(rs[x],y);update(x);return x;}
    else{ls[y]=merge(x,ls[y]);update(y);return y;}
}
void ins(int &RT,int k){
    int l,r;
    split(RT,k,l,r);
    RT=merge(merge(l,New(k)),r);
}
void del(int &RT,int k){
    int x,y,z;
    split(RT,k,x,z);
    split(x,k-1,x,y);
    if(y)y=merge(ls[y],rs[y]);
    RT=merge(merge(x,y),z);
}
int rnk(int &RT,int k){
    int x,y,ANS;
    split(RT,k-1,x,y);
    ANS=siz[x];
    RT=merge(x,y);
    return ANS;
}
int kth(int &RT,int k){
    int p=RT;
    while("xgy"){
        if(siz[ls[p]]+1==k)break;
        else if(siz[ls[p]]+1>k)p=ls[p];
        else k-=siz[ls[p]]+1,p=rs[p];
    }return val[p];
}
int pre_nxt(int &RT,int k,int op){
    int x,y,p,ANS;
    k-=op;
    split(RT,k,x,y);
    p=op?x:y;
    if(op)while(rs[p])p=rs[p];
    else while(ls[p])p=ls[p];
    ANS=val[p];
    RT=merge(x,y);
    return ANS;
}
void build(int p,int l,int r){
    if(l==r){
        rt[p]=New(a[l]);
        ins(rt[p],inf);ins(rt[p],-inf);
        return;
    }
    for(int i=l;i<=r;i++)ins(rt[p],a[i]);
    ins(rt[p],inf);ins(rt[p],-inf);
    int mid=l+r>>1;
    build(lson);build(rson);
}
void change(int p,int l,int r,int x,int v){
    del(rt[p],a[x]);ins(rt[p],v);
    if(l==r)return;
    int mid=l+r>>1;
    if(x<=mid)change(lson,x,v);
    else change(rson,x,v);
}
void query_pre(int p,int l,int r,int x,int y,int k){
    if(x<=l&&y>=r){Ans=max(Ans,pre_nxt(rt[p],k,1));return;}
    int mid=l+r>>1;
    if(x<=mid)query_pre(lson,x,y,k);
    if(y>mid)query_pre(rson,x,y,k);
}
void query_nxt(int p,int l,int r,int x,int y,int k){
    if(x<=l&&y>=r){Ans=min(Ans,pre_nxt(rt[p],k,0));return;}
    int mid=l+r>>1;
    if(x<=mid)query_nxt(lson,x,y,k);
    if(y>mid)query_nxt(rson,x,y,k);
}
void query_rnk(int p,int l,int r,int x,int y,int k){
    if(x<=l&&y>=r){Ans+=rnk(rt[p],k)-1;return;}
    int mid=l+r>>1;
    if(x<=mid)query_rnk(lson,x,y,k);
    if(y>mid)query_rnk(rson,x,y,k);
}
int ask(int x,int y,int k){
    int l=0,r=1e8;
    while(l<=r){
        Ans=1;
        int mid=l+r>>1;
        query_rnk(1,1,n,x,y,mid);
        if(Ans<=k)l=mid+1;
        else r=mid-1;
    }return r;
}
int main(){
    srand(time(0));
    scanf("%d%d",&n,&T);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    build(1,1,n);
    while(T--){
        int op,l,r,k;
        scanf("%d",&op);
        if(op==1){
            Ans=1;
            scanf("%d%d%d",&l,&r,&k);
            query_rnk(1,1,n,l,r,k);
            printf("%d\n",Ans);
        }else if(op==2){
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",ask(l,r,k));
        }else if(op==3){
            scanf("%d%d",&l,&r);
            change(1,1,n,l,r);
            a[l]=r;
        }else if(op==4){
            Ans=-inf;
            scanf("%d%d%d",&l,&r,&k);
            query_pre(1,1,n,l,r,k);
            printf("%d\n",Ans);
        }else{
            Ans=inf;
            scanf("%d%d%d",&l,&r,&k);
            query_nxt(1,1,n,l,r,k);
            printf("%d\n",Ans);
        } 
    }
    return 0;
}
View Code

树套树 主席树套树状数组 https://www.luogu.com.cn/problem/P2617

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
int n,T,m,tot;
int a[N],b[N<<2],rt[N<<7];
int ls[N<<7],rs[N<<7],dat[N<<7],cnt;
int LT[N],RT[N],lc,rc;
struct{
    int l,r,k;
    int op;
}q[N<<2];
void copy(int x,int y,int val){
    ls[x]=ls[y];
    rs[x]=rs[y];
    dat[x]=dat[y]+val;
}
int build(int l,int r){
    int p=++cnt;
    if(l==r)return p;
    int mid=l+r>>1;
    ls[p]=build(l,mid);
    rs[p]=build(mid+1,r);
    return p;
}
int insert(int pre,int l,int r,int x,int val){
    int p=++cnt;
    copy(p,pre,val);
    if(l==r)return p;
    int mid=l+r>>1;
    if(x<=mid)ls[p]=insert(ls[pre],l,mid,x,val);
    else rs[p]=insert(rs[pre],mid+1,r,x,val);
    return p;
}
int query(int l,int r,int k){
    if(l==r)return l; 
    int sum=0,mid=l+r>>1;
    for(int i=1;i<=lc;i++)sum-=dat[ls[LT[i]]];
    for(int i=1;i<=rc;i++)sum+=dat[ls[RT[i]]];
    if(k<=sum){
        for(int i=1;i<=lc;i++)LT[i]=ls[LT[i]];
        for(int i=1;i<=rc;i++)RT[i]=ls[RT[i]];
        return query(l,mid,k);
    }
    else{
        for(int i=1;i<=lc;i++)LT[i]=rs[LT[i]];
        for(int i=1;i<=rc;i++)RT[i]=rs[RT[i]];
        return query(mid+1,r,k-sum);
    }
}
void add(int x,int val){
    int t=lower_bound(b+1,b+m+1,a[x])-b;
    for(;x<=N-10;x+=x&-x)
        rt[x]=insert(rt[x],1,m,t,val);
    return;
}
int main(){
    scanf("%d%d",&n,&T);tot=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        b[++tot]=a[i];
    }
    for(int i=1;i<=T;i++){
        char Op[3];
        scanf("%s%d%d",Op,&q[i].l,&q[i].r);
        if(Op[0]=='Q'){
            scanf("%d",&q[i].k);
            q[i].op=0;
        }
        else q[i].op=1,b[++tot]=q[i].r;
    }
    sort(b+1,b+tot+1);
    m=unique(b+1,b+tot+1)-b-1;
    rt[0]=build(1,m);
    for(int i=1;i<=n;i++)add(i,1);
    for(int i=1;i<=T;i++){
        if(q[i].op==1){
            add(q[i].l,-1);
            a[q[i].l]=q[i].r;
            add(q[i].l,1);
        }
        else{
            lc=rc=0;
            int L=q[i].l-1,R=q[i].r;
            for(;L;L-=L&-L)LT[++lc]=rt[L];
            for(;R;R-=R&-R)RT[++rc]=rt[R];
            printf("%d\n",b[query(1,m,q[i].k)]);
        }
    }
    return 0;
}
View Code

 线性基 https://www.luogu.com.cn/problem/P3812

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int n,a[N],p[N],ans;
void ins(int x){
    for(int i=62;i>=0;i--){
        if(!(x>>i))continue;
        if(!p[i]){p[i]=x;break;}
        x^=p[i];
    }
}
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        ins(a[i]);
    }
    for(int i=62;i>=0;i--)ans=max(ans,ans^p[i]);
    printf("%lld\n",ans);
    return 0;
}
View Code

 标记永久化 http://acm.hdu.edu.cn/showproblem.php?pid=4348

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+1;
int n,q,tot;
int a[N],rt[N],ls[N*19],rs[N*19];
int sum[N*19],add[N*19];
int now=0;
int read(){
    int a=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){a=(a<<1)+(a<<3)+c-'0';c=getchar();}
    return a*f;
}
void update(int p){
    sum[p]=sum[ls[p]]+sum[rs[p]];
}
void build(int &p,int l,int r){
    //if(!p)
    p=++tot;
    if(l==r){
        sum[p]=a[l];
        return;
    }
    int mid=l+r>>1;
    build(ls[p],l,mid);
    build(rs[p],mid+1,r);
    update(p);
}
void copy(int x,int y){
    ls[x]=ls[y];
    rs[x]=rs[y];
    add[x]=add[y];
    sum[x]=sum[y];
}
void insert(int &p,int pre,int l,int r,int x,int y,int v){
   // if(!p)
    p=++tot;
    copy(p,pre);
    if(x<=l&&y>=r){
        add[p]+=v;
        sum[p]+=1LL*(r-l+1)*v;
        return;
    }
    int mid=l+r>>1;
    if(x<=mid)insert(ls[p],ls[pre],l,mid,x,y,v);
    if(y>mid)insert(rs[p],rs[pre],mid+1,r,x,y,v);
    sum[p]=sum[ls[p]]+sum[rs[p]]+1LL*(r-l+1)*add[p];
    return;
}
long long query(int p,int l,int r,int x,int y,long long v){
    if(x<=l&&y>=r)return sum[p]+v*1LL*(r-l+1);
    int mid=l+r>>1;
    long long ans=0;
    if(x<=mid)ans+=query(ls[p],l,mid,x,y,v+add[p]);
    if(y>mid)ans+=query(rs[p],mid+1,r,x,y,v+add[p]);
    return ans;
}
void Clear(){
    now=tot=0;
    for(int i=0;i<=N-1;i++)rt[i]=0;
    for(int i=0;i<=(n*19)-1;i++)
        sum[i]=add[i]=ls[i]=rs[i]=0;
}
signed main(){
    while(~scanf("%lld%lld",&n,&q)){
        Clear();
        for(int i=1;i<=n;i++)
            a[i]=read();
        build(rt[0],1,n);
        while(q--){
            char op[3];int l,r,t;
            scanf("%s",op);
            if(op[0]=='B'){
                int tmp;
                tmp=read();
                if(tmp!=now){
                    now=tmp;
                    tot=rt[now+1]-1;
                }
            }
            else if(op[0]=='C'){
                ++now;
                l=read();r=read();t=read();
                insert(rt[now],rt[now-1],1,n,l,r,t);
            }
            else if(op[0]=='Q'){
                l=read();r=read();
                printf("%lld\n",query(rt[now],1,n,l,r,0));
            }
            else if(op[0]=='H'){
                l=read();r=read();t=read();
                printf("%lld\n",query(rt[t],1,n,l,r,0));
            }
        }
    }
    return 0;
}
View Code

 四维偏序 http://acm.hdu.edu.cn/showproblem.php?pid=5126

#include<bits/stdc++.h>
#define NMsl x1
#define NmSl x2
#define NmsL y1 
#define NmSL y2 
#define nmsl z1
#define NMSL z2
#define ll long long
using namespace std;
const int N=4e5+2;
int C[N],ans[N];
int cnt,tz[N];
int read(){
    int a=0;
    char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while(c>='0'&&c<='9'){a=(a<<1)+(a<<3)+c-'0';c=getchar();}
    return a;
}
struct node{
    int x,y,z;
    int op,pos,pt;
    node(){}
    node(int X,int Y,int Z,int Op,int Pos,int Pt){
        x=X;y=Y;z=Z;op=Op;pos=Pos;pt=Pt;
    }
}a[N],tmp[N],tmp2[N];
bool cmp1(node A,node B){return A.x<B.x;}
bool cmp2(node A,node B){return A.y<B.y;}
void add(int x,int k){for(;x<=N-1;x+=x&-x)C[x]+=k;}
int ask(int x){int sum=0;for(;x;x-=x&-x)sum+=C[x];return sum;}
void clear(){cnt=0;memset(ans,0,sizeof(ans));}
void cdq2(int l,int r){
    if(l>=r)return;
    int mid=l+r>>1;
    cdq2(l,mid);
    cdq2(mid+1,r);
    int i=l,j=mid+1;
    for(;j<=r;j++){
        for(;i<=mid&&tmp[i].y<=tmp[j].y;i++)
            if(tmp[i].pt==-1&&tmp[i].pos==0)add(tmp[i].z,1);
        if(tmp[j].pt==1&&tmp[j].pos)ans[tmp[j].pos]+=ask(tmp[j].z)*tmp[j].op;
    }
    while(--i>=l)if(tmp[i].pt==-1&&!tmp[i].pos)add(tmp[i].z,-1);
    i=l,j=mid+1;
    int ck=l;
    while(i<=mid&&j<=r){
        if(tmp[i].y<=tmp[j].y)
            tmp2[ck++]=tmp[i++];
        else tmp2[ck++]=tmp[j++];
    }
    while(i<=mid)tmp2[ck++]=tmp[i++];
    while(j<=r)tmp2[ck++]=tmp[j++];
    for(int k=l;k<=r;k++)tmp[k]=tmp2[k];
}
void cdq1(int l,int r){
    if(l==r)return;
    int mid=l+r>>1;
    cdq1(l,mid);
    cdq1(mid+1,r);
    sort(a+l,a+mid+1,cmp1);
    sort(a+mid+1,a+r+1,cmp1); 
    int i=l,j=mid+1,sd=0;
    while(i<=mid&&j<=r){
        if(a[i].x<=a[j].x){
            tmp[++sd]=a[i++];
            tmp[sd].pt=-1;
            if(a[i-1].pos)sd--;
        }else{
            tmp[++sd]=a[j++];
            tmp[sd].pt=1;
            if(!a[j-1].pos)sd--;
        }
    }
    while(i<=mid)tmp[++sd]=a[i++],tmp[sd].pt=-1;
    while(j<=r)tmp[++sd]=a[j++],tmp[sd].pt=1;
    cdq2(1,sd);
}
int main(){
    int T;
    T=read(); 
    while(T--){
        clear();
        int q,qcnt=0;
        int zcnt=0;
        q=read();
        for(int i=1;i<=q;i++){
            int Op;
            Op=read();
            if(Op==1){
                int x,y,z;
                x=read();y=read();z=read();
                ++cnt;
                a[cnt]=node{x,y,z,0,0,0};
                tz[++zcnt]=z;
            }else{
                int x1,y1,z1;
                int x2,y2,z2;
                qcnt++;
                x1=read();y1=read();z1=read();
                x2=read();y2=read();z2=read();
                a[++cnt]=node{x2,y2,z2,1,qcnt,0};
                a[++cnt]=node{x2,y2,z1-1,-1,qcnt,0};
                a[++cnt]=node{x2,y1-1,z2,-1,qcnt,0};
                a[++cnt]=node{x2,y1-1,z1-1,1,qcnt,0};
                a[++cnt]=node{x1-1,y2,z2,-1,qcnt,0};
                a[++cnt]=node{x1-1,y2,z1-1,1,qcnt,0};
                a[++cnt]=node{x1-1,y1-1,z2,1,qcnt,0};
                a[++cnt]=node{x1-1,y1-1,z1-1,-1,qcnt,0};
                tz[++zcnt]=z1-1;
                tz[++zcnt]=z2;
            }
        }
        sort(tz+1,tz+zcnt+1);
        int fk=unique(tz+1,tz+zcnt+1)-(tz+1);
        for(int i=1;i<=cnt;i++)
            a[i].z=lower_bound(tz+1,tz+fk+1,a[i].z)-tz;
        cdq1(1,cnt);
        for(int i=1;i<=qcnt;i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}
View Code

 三维偏序 https://www.luogu.com.cn/problem/P3810

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+11;
int n,k,C[N],f[N],cnt[N];
map<long long,int>mp,MP,bk;
void add(int x,int v){
    for(;x<=k;x+=x&-x)C[x]+=v;
}
int ask(int x){
    int sum=0;
    for(;x;x-=x&-x)sum+=C[x];
    return sum;
}
struct Node{
    int a,b,c,ans,wz;
    long long hs;
}s[N];
bool cmp1(Node A,Node B){
    if(A.a==B.a){
        if(A.b==B.b)return A.c<B.c;
        return A.b<B.b;
    }
    return A.a<B.a;
}
bool cmp2(Node A,Node B){
    if(A.b==B.b)return A.c<B.c;
    return A.b<B.b;
}
void cdq(int l,int r){
    if(l==r)return;
    int mid=l+r>>1;
    cdq(l,mid);cdq(mid+1,r);
    sort(s+l,s+mid+1,cmp2);
    sort(s+mid+1,s+r+1,cmp2);
    int i=mid+1,j=l;
    for(;i<=r;i++){
        while(s[j].b<=s[i].b&&j<=mid)
            add(s[j].c,1),j++;
        s[i].ans+=ask(s[i].c);
    }
    for(int i=l;i<j;i++)add(s[i].c,-1);
}
long long Hash(long long X,long long Y,long long Z){
    return X*(N-10)*(N-10)+Y*(N-10)+Z;
}
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&s[i].a,&s[i].b,&s[i].c);
        s[i].hs=Hash(s[i].a,s[i].b,s[i].c);
        mp[s[i].hs]++;
    }
    sort(s+1,s+n+1,cmp1);
    for(int i=1;i<=n;i++){
        bk[s[i].hs]=i;
        s[i].wz=i;
    }
    cdq(1,n);
    for(int i=1;i<=n;i++){
        if(s[i].wz==bk[s[i].hs]){
            f[s[i].ans]+=mp[s[i].hs];
        }
    }
    for(int i=0;i<n;i++)printf("%d\n",f[i]);
    return 0;
}
View Code

 LCT动态树 https://www.luogu.com.cn/problem/P3690

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int f[N],ch[N][2],a[N],ret[N],tag[N];
int n,T;
bool isrt(int x){return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;}
void pushup(int x){ret[x]=a[x]^ret[ch[x][0]]^ret[ch[x][1]];}
void pushrev(int x){
    if(!x)return;
    tag[x]^=1;
    swap(ch[x][0],ch[x][1]);
}
void pushdown(int x){
    if(!tag[x])return;
    pushrev(ch[x][0]);
    pushrev(ch[x][1]);
    tag[x]=0;
}
void update(int x){if(!isrt(x))update(f[x]);pushdown(x);}
int get(int x){return ch[f[x]][1]==x;}
void rotate(int x){
    int y=f[x],z=f[y],k=get(x);
    if(!isrt(y))ch[z][ch[z][1]==y]=x;
    ch[y][k]=ch[x][k^1];f[ch[x][k^1]]=y;
    ch[x][k^1]=y;f[y]=x;f[x]=z;
    pushup(y);pushup(x);pushup(z);
}
void splay(int x){
    update(x);
    for(int fa;fa=f[x],!isrt(x);rotate(x))
        if(!isrt(fa))rotate(get(fa)==get(x)?fa:x);
}
int access(int x){
    int p=0;
    for(;x;p=x,x=f[x]){
        splay(x);ch[x][1]=p;pushup(x);
    }return p;
}
void mkrt(int x){
    access(x);splay(x);
    swap(ch[x][0],ch[x][1]);
    tag[x]^=1;
}
int find(int x){
    access(x);splay(x);pushdown(x); 
    while(ch[x][0])pushdown(x=ch[x][0]);
    splay(x);return x;
}
void split(int x,int y){
    mkrt(x);access(y);splay(y);
}
void link(int x,int y){
    if(find(x)!=find(y)){mkrt(x);f[x]=y;}
}
void cut(int x,int y){
    if(find(x)!=find(y))return;
    split(x,y);
    if(ch[y][0]==x&&!ch[x][1])
        ch[y][0]=f[x]=0;
    pushup(x);
}
void change(int x,int y){a[x]=y;splay(x);}
int query(int x,int y){split(x,y);return ret[y];}
int main(){ 
    scanf("%d%d",&n,&T);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    while(T--){
        int op,x,y;
        scanf("%d%d%d",&op,&x,&y);
        if(op==0)printf("%d\n",query(x,y));
        else if(op==1)link(x,y);
        else if(op==2)cut(x,y);
        else change(x,y);
    }
    return 0;
}
View Code

 带权并查集 https://www.luogu.com.cn/problem/P1196

#include<bits/stdc++.h>
using namespace std;
const int N=3e4+5;
int T,fa[N],d[N],siz[N];
int find(int x){
    if(x==fa[x])return x;
    int p=find(fa[x]);
    d[x]+=d[fa[x]];
    return fa[x]=p;
}
void merge(int x,int y){
    x=find(x);y=find(y);
    fa[x]=y;d[x]=siz[y];
    siz[y]+=siz[x];
}
int main(){
    for(int i=1;i<=N-5;i++)
        fa[i]=i,siz[i]=1;
    int T;
    scanf("%d",&T);
    while(T--){
        char op[3];int x,y;
        scanf("%s %d %d",op,&x,&y);
        if(op[0]=='M'){
            merge(x,y);
        }else{
            int fx=find(x),fy=find(y);
            if(fx!=fy)puts("-1");
            else printf("%d\n",abs(d[x]-d[y])-1);
        }
    }    
    return 0;
}
View Code

 Lucas定理 https://www.luogu.com.cn/problem/P3807

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5;
int p;
int ksm(int a,int b){
    int ans=1%p;
    for(;b;b>>=1){
        if(b&1)ans=1LL*ans*a%p;
        a=1LL*a*a%p;
    }
    return ans%p;
}
int C(int n,int m){
    if(n<m)return 0;
    int r1=1,r2=1,r3=1;
    for(int i=1;i<=m;i++)r3=1LL*r3*i%p;
    for(int i=1;i<=n;i++)r1=1LL*r1*i%p;
    for(int i=1;i<=n-m;i++)r2=1LL*r2*i%p;
    return 1LL*r1*ksm(r2,p-2)%p*ksm(r3,p-2)%p;
}
int Lucas(int n,int m){
    if(m==0)return 1;
    return 1LL*Lucas(n/p,m/p)%p*C(n%p,m%p)%p;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n,m;
        scanf("%d%d%d",&n,&m,&p);
        printf("%d\n",Lucas(n+m,n));
    }
    return 0;
}
View Code

 Splay 区间操作 https://www.luogu.com.cn/problem/P4036

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int B=31,mod=998244353,N=6e5+5;
char s[N];int root,sz,T;
int p[N],val[N],hs[N],f[N],siz[N],ch[N][2];
int get(int u){return ch[f[u]][1]==u;}
void update(int u){
    if(!u)return;siz[u]=1;
    if(ch[u][0])siz[u]+=siz[ch[u][0]];
    if(ch[u][1])siz[u]+=siz[ch[u][1]];
    hs[u]=(hs[ch[u][0]]+1LL*val[u]*p[siz[ch[u][0]]]%mod)%mod+1LL*hs[ch[u][1]]*p[siz[ch[u][0]]+1]%mod;
    hs[u]%=mod;
}
void build(int l,int r,int u){
    if(l>r)return;
    int mid=l+r>>1;
    if(u<=mid)ch[u][1]=mid;
    else ch[u][0]=mid;
    f[mid]=u;siz[mid]=1;
    if(l==r)return;
    build(l,mid-1,mid);
    build(mid+1,r,mid);
    update(mid);
}
void rotate(int u){
    int fa=f[u],gf=f[fa],wh=get(u);
    ch[fa][wh]=ch[u][wh^1];
    f[ch[fa][wh]]=fa;
    ch[u][wh^1]=fa;
    f[u]=gf;f[fa]=u;
    if(gf)ch[gf][ch[gf][1]==fa]=u;
    update(fa);update(u);
}
void splay(int u,int goal){
    for(int fa;(fa=f[u])!=goal;rotate(u))
        if(f[fa]!=goal)rotate(get(fa)==get(u)?fa:u);
    if(!goal)root=u;
}
int find(int x){
    int u=root;
    while("cnyz ak ioi"){
        if(siz[ch[u][0]]+1==x)return u;
        if(siz[ch[u][0]]+1<x){
            x-=siz[ch[u][0]]+1;
            u=ch[u][1];
        }else u=ch[u][0];
    }
}
void ins(int x,int v){
    int pre=find(x+1),nxt=find(x+2);
    splay(pre,0);
    splay(nxt,pre);
    ch[nxt][0]=++sz;
    f[sz]=nxt;hs[sz]=val[sz]=v;
    splay(sz,0);
}
int Hash(int l,int r){
    int x=find(l),y=find(r+2);
    splay(x,0);splay(y,x);
    int fx=ch[y][0];return hs[fx];
}
signed main(){
    scanf("%s",s+1);
    int n=strlen(s+1);p[0]=1;
    for(int i=1;i<=n*2;i++)p[i]=p[i-1]*B%mod;
    for(int i=2;i<=n+1;i++)val[i]=hs[i]=s[i-1]-'a'+1;
    build(1,n+2,root);
    root=(n+3)>>1,sz=n+2;
    scanf("%lld",&T);
    while(T--){
        char op[2],c[2];int x,y;
        scanf("%s",op);
        if(op[0]=='Q'){
            scanf("%lld%lld",&x,&y);
            if(x>y)swap(x,y);
            int l=0,r=sz-y-1;
    //        cout<<sz<<' '<<y<<endl;
            while(l<=r){
                int mid=l+r>>1;
//                cout<<mid<<endl;
                if(Hash(x,x+mid-1)==Hash(y,y+mid-1))l=mid+1;
                else r=mid-1;
            }
            printf("%lld\n",r);
        }else if(op[0]=='R'){
            scanf("%lld %s",&x,c);
            char cs=c[0];
            splay(find(x+1),0);
            val[root]=cs-'a'+1;
            update(root);
        }else if(op[0]=='I'){
            scanf("%lld %s",&x,c);
            char cs=c[0];
            ins(x,cs-'a'+1);
        }
    }return 0;
}
View Code

 莫队 https://www.luogu.com.cn/problem/P1494

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,T,t,cnt[N],a[N];
int ans;
struct seg{int l,r,id;}q[N],ret[N];
bool cmp(seg A,seg B){
    if(A.l/t!=B.l/t)return A.l/t<B.l/t;
    if((A.l/t)&1)return A.r<B.r;
    return A.r>B.r;
}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
void add(int x){
    ans-=(1LL*cnt[a[x]]*(cnt[a[x]]-1))>>1;
    cnt[a[x]]++;
    ans+=(1LL*cnt[a[x]]*(cnt[a[x]]-1))>>1;
}
void del(int x){
    ans-=(1LL*cnt[a[x]]*(cnt[a[x]]-1))>>1;
    cnt[a[x]]--;
    ans+=(1LL*cnt[a[x]]*(cnt[a[x]]-1))>>1;
}
signed main(){
    scanf("%lld%lld",&n,&T);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    for(int i=1;i<=T;i++){
        scanf("%lld%lld",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    t=sqrt(T);
    sort(q+1,q+T+1,cmp);
    int l=1,r=0;
    for(int i=1;i<=T;i++){
        while(l<q[i].l)del(l++);
        while(l>q[i].l)add(--l);
        while(r<q[i].r)add(++r);
        while(r>q[i].r)del(r--);
        int up=ans,down=(r-l+1)*(r-l)>>1;
        if(r==l){
            ret[q[i].id].l=0;
            ret[q[i].id].r=1;
            continue;
        }
        int G=gcd(up,down);
        up/=G;down/=G;
        ret[q[i].id].l=up;
        ret[q[i].id].r=down;
    }
    for(int i=1;i<=T;i++)
        printf("%lld/%lld\n",ret[i].l,ret[i].r); 
    return 0;
}
View Code

 欧拉回路 无向图

#include<bits/stdc++.h>
using namespace std;
const int M=4e5+10;
int n,m,tot=1,t;
int ans[M],sk[M],top;
int nxt[M],head[M],to[M];
bool vis[M];
void add(int x,int y){
    nxt[++tot]=head[x];
    head[x]=tot;to[tot]=y;
}
void euler(){
    sk[++top]=1;
    while(top){
        int u=sk[top],i=head[u];
        while(i&&vis[i])i=nxt[i];
        if(i)sk[++top]=to[i],head[u]=nxt[i],vis[i]=vis[i^1]=true;
        else top--,ans[++t]=u;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){    
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    euler();
    for(int i=t;i;i--)printf("%d\n",ans[i]);
    return 0;
}
View Code

欧拉路径 有向图 https://www.luogu.com.cn/problem/P7771

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
int n,m,pr[N];
vector<int>G[N],id[N];
int in[N],out[N];bool vis[N];
int sk[N],top;
void dfs(int u){
    int sze=G[u].size();
    for(int i=pr[u];i<sze;i=max(i+1,pr[u])){
        int v=G[u][i],ine=id[u][i];
        if(!vis[ine]){
            vis[ine]=true;
            pr[u]=i+1;
            dfs(v);
        }
    }
    sk[++top]=u;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        id[u].push_back(i);
        in[v]++;out[u]++;
    }
    for(int i=1;i<=n;i++)sort(G[i].begin(),G[i].end());
    int st=0,ed=0,cnt=0;
    for(int i=1;i<=n;i++){
        if(in[i]==out[i])continue;
        if(in[i]==out[i]+1)ed=i,cnt++;
        if(in[i]+1==out[i])st=i,cnt++;
    }
    if((cnt!=0&&cnt!=2))return puts("No")&0;
    if(!cnt)st=1;dfs(st);
    while(top)printf("%d ",sk[top--]);
    return 0;
}
View Code

整体二分 https://www.luogu.com.cn/problem/P7424

#include<bits/stdc++.h>
using namespace std;
const int N=6e5+5;
struct Que{
    int id,l,r,s,tim;
    Que(){id=0;}
}q[N],lq[N],rq[N];
int c[N],MX,res[N];
void add(int x,int k){
    for(;x<=MX;x+=x&-x)c[x]+=k;
}
int ask(int x){
    int S=0;
    for(;x;x-=x&-x)S+=c[x];
    return S;
}
int n,m,ans[N];
void solve(int L,int R,int l,int r){
    if(l>r)return;
    if(L==R){
        for(int i=l;i<=r;i++)ans[q[i].id]=L;
        return;
    }
    int mid=L+R>>1,lt=0,rt=0;
    for(int i=l;i<=r;i++){
        if(!q[i].id){
            if(q[i].tim<=mid)lq[++lt]=q[i],add(q[i].l,1);
            else rq[++rt]=q[i];
        }else{
            int k=ask(q[i].r)-ask(q[i].l-1);
            if(q[i].s<=k)lq[++lt]=q[i];
            else q[i].s-=k,rq[++rt]=q[i];
        }
    }
    for(int i=1;i<=lt;i++)if(!lq[i].id)add(lq[i].l,-1);
    for(int i=1;i<=lt;i++)q[l+i-1]=lq[i];
    for(int i=1;i<=rt;i++)q[l+lt+i-1]=rq[i];
    solve(L,mid,l,l+lt-1);
    solve(mid+1,R,l+lt,r);
}
int main(){
    //freopen("ex1.in","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&q[m+i].l,&q[m+i].r,&q[m+i].s);
        q[m+i].id=i;
        MX=max(MX,q[m+i].r);
    }
    MX=2e5;
    for(int i=1;i<=m;i++){
        scanf("%d",&q[i].l);
        q[i].tim=i;q[i].id=0;
    }
    solve(1,m+1,1,n+m);
    for(int i=1;i<=n;i++)res[ans[i]]++;
    for(int i=1;i<=m;i++)printf("%d\n",res[i]);
    return 0;
}
/*
3 5 
1 3 2 
4 5 5 
3 5 5

5 
4 
5 
3 
1
*/
View Code

二维hash https://www.luogu.com.cn/problem/P4398

#include<bits/stdc++.h>
using namespace std;
const int N=55;
const int B1=31,B2=37;
const int P=1e9+7;
int h[N][N],a[N][N],H[N][N],b[N][N],n;
int pw1[N],pw2[N];
map<int,int>mp;
int get(int op,int i,int j,int k,int l){
    if(op==0){
        int V1=h[i][j];
        int V2=1LL*h[i][l-1]*pw1[j-l+1]%P;
        int V3=1LL*h[k-1][j]*pw2[i-k+1]%P;
        int V4=1LL*h[k-1][l-1]*pw1[i-k+1]%P*pw2[j-l+1]%P;
        return ((1LL*V1-V2-V3+V4)%P+P)%P;
    }else{
        int V1=H[i][j];
        int V2=1LL*H[i][l-1]*pw1[j-l+1]%P;
        int V3=1LL*H[k-1][j]*pw2[i-k+1]%P;
        int V4=1LL*H[k-1][l-1]*pw1[i-k+1]%P*pw2[j-l+1]%P;
        return ((1LL*V1-V2-V3+V4)%P+P)%P;
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)scanf("%d",&a[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)scanf("%d",&b[i][j]);
    pw1[0]=pw2[0]=1;
    for(int i=1;i<=n;i++){
        pw1[i]=1LL*pw1[i-1]*B1%P;
        pw2[i]=1LL*pw2[i-1]*B2%P;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            h[i][j]=(1LL*h[i][j-1]*B1%P+a[i][j])%P;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            h[i][j]+=1LL*h[i-1][j]*B2%P;    
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            H[i][j]=(1LL*H[i][j-1]*B1%P+b[i][j])%P;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            H[i][j]+=1LL*H[i-1][j]*B2%P;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int len=1;len<=n;len++){
                if(i+len-1>n||j+len-1>n)continue;
                mp[get(0,i+len-1,j+len-1,i,j)]=true;
            }
    int ans=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int len=1;len<=n;len++){
                if(i+len-1>n||j+len-1>n)continue;
                if(mp[get(1,i+len-1,j+len-1,i,j)])ans=max(ans,len);   
            }
    printf("%d\n",ans);
    return 0;
}
View Code

大可并堆板子 https://www.luogu.com.cn/problem/P3273

#include<bits/stdc++.h>
using namespace std;
const int N=6e5+5;
int n,m,add;
int ls[N],rs[N],dis[N],val[N],fa[N];
int f[N],siz[N],tag[N];
int find(int x){
    return f[x]==x?x:f[x]=find(f[x]);
}//hht 下面好大
void pushup(int x){
    if(!x)return;
    if(dis[x]!=dis[rs[x]]+1){
        dis[x]=dis[rs[x]]+1;
        pushup(fa[x]);
    }
}
int merge(int x,int y){
    if(!x||!y)return x|y;
    if(val[x]<val[y])swap(x,y);
    rs[x]=merge(rs[x],y);
    fa[rs[x]]=x;fa[ls[x]]=x;
    if(dis[rs[x]]>dis[ls[x]])swap(ls[x],rs[x]);
    pushup(x);return x;
}
void pushdown(int p,int v){
    if(!p)return;
    val[p]+=v;
    pushdown(ls[p],v);
    pushdown(rs[p],v);
}
multiset<int>s;
int main(){
    //freopen("ex.in","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&val[i]);
        siz[i]=1;f[i]=i;
        s.insert(val[i]);
    }
    scanf("%d",&m);
    while(m--){
        char op[5];int x,y,v;
        scanf("%s",op);
        if(op[0]=='U'){
            scanf("%d%d",&x,&y);
            x=find(x);y=find(y);
            if(x==y)continue;
            if(siz[x]>siz[y])swap(x,y);
            pushdown(x,tag[x]-tag[y]);
            f[x]=f[y]=merge(x,y); 
            if(f[x]==x){
                s.erase(s.find(val[y]+tag[y]));
                tag[x]=tag[y];
                siz[x]+=siz[y];
                tag[y]=siz[y]=0;
            }else{
                s.erase(s.find(val[x]+tag[y]));
                siz[y]+=siz[x];
                tag[x]=siz[x]=0;
            }
        }else if(op[0]=='A'){
            if(op[1]=='1'){
                scanf("%d%d",&x,&v);
                if(x==find(x)){
                    fa[ls[x]]=fa[rs[x]]=0;
                    y=merge(ls[x],rs[x]);
                    s.erase(s.find(val[x]+tag[x]));
                    val[x]+=v;
                    fa[x]=ls[x]=rs[x]=0;
                    dis[x]=1;
                    f[x]=f[y]=merge(x,y);
                    s.insert(val[f[x]]+tag[x]);
                    if(f[x]==y){
                        tag[y]=tag[x];
                        siz[y]=siz[x];
                        tag[x]=siz[x]=0;
                    }
                }else{
                    fa[ls[x]]=fa[rs[x]]=fa[x];
                    if(ls[fa[x]]==x)ls[fa[x]]=merge(ls[x],rs[x]);
                    else rs[fa[x]]=merge(ls[x],rs[x]);
                    val[x]+=v;
                    fa[x]=ls[x]=rs[x]=0;
                    dis[x]=1;
                    y=find(x);
                    f[x]=f[y]=merge(x,y);
                    if(f[x]==x){
                        s.erase(s.find(val[y]+tag[y]));
                        s.insert(val[x]+tag[y]);
                        tag[x]=tag[y];
                        siz[x]=siz[y];
                        siz[y]=tag[y]=0;
                    }
                }
            }
            else if(op[1]=='2'){
                scanf("%d%d",&x,&v);
                x=find(x);
                s.erase(s.find(val[x]+tag[x]));
                tag[x]+=v;
                s.insert(val[x]+tag[x]);
            }else{
                scanf("%d",&v);add+=v;
            }
        }else if(op[1]=='1'){
            scanf("%d",&x);
            printf("%d\n",val[x]+tag[find(x)]+add);
        }else if(op[1]=='2'){
            scanf("%d",&x);
            x=find(x);
            printf("%d\n",val[x]+tag[x]+add);
        }else{
            printf("%d\n",*s.rbegin()+add);
        }
    }
    return 0;
}
View Code

匈牙利 二分图最大匹配 https://www.luogu.com.cn/problem/P3386

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int head[N],nxt[N],to[N],tot;
int vis[N],tag,path[N],n,m,e,ans;
void add(int x,int y){nxt[++tot]=head[x];head[x]=tot;to[tot]=y;}
bool dfs(int u){
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(vis[v]==tag)continue;
        vis[v]=tag;
        if(!path[v]||dfs(path[v])){path[v]=u;return 1;}
    }
    return 0;
}
int main(){
    scanf("%d%d%d",&n,&m,&e);
    for(int i=1;i<=e;i++){int x,y;scanf("%d%d",&x,&y);add(x,y);}
    for(int i=1;i<=n;i++){tag++;if(dfs(i))ans++;}
    printf("%d\n",ans);
}
View Code

 dp求树的直径 

void dp(int x){
    v[x]=1;    
    for(register int i=head[x];i;i=nxt[i]){
        int y=to[i],Val=edge[i];
        if(v[y])continue;    
        dp(y); 
        ans=max(ans,d[x]+d[y]+Val);
        d[x]=max(d[x],d[y]+Val);
    }
}
View Code

dfs求树的重心

void findrt(int u,int F){
    me[u]=0;siz[u]=1;
    for(int i=now[u];i;i=pre[i]){
        int v=to[i];
        if(v==F||vis[v])continue;
        findrt(v,u); 
        siz[u]+=siz[v];
        me[u]=max(me[u],siz[v]);
    }
    me[u]=max(me[u],ns-siz[u]);
    if(me[u]<me[rt])rt=u;
}
View Code

 基环树找奇环

void find(int u){
    dfn[u]=++idx;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(v==dad[u])continue;
        if(dfn[v]){
            if(dfn[v]<dfn[u])continue;
            lp[++cnt]=v;
            vis[lp[cnt]]=true;
            for(;v!=u;v=dad[v])
                lp[++cnt]=dad[v],vis[lp[cnt]]=true;
        }else dad[v]=u,find(v);
    }
}
View Code

 数位dp https://www.luogu.com.cn/problem/P4999

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7,N=22;
int len,a[N],f[N][N*11];
int dfs(int pos,int sum,bool fl,int lim){
    if(!pos)return sum%mod;
    if(!lim&&f[pos][sum]!=-1)return f[pos][sum];
    int ret=0,mx=lim?a[pos]:9;
    for(int i=0;i<=mx;i++)
        if(fl&&i==0)ret+=dfs(pos-1,0,1,lim&&i==mx),ret%=mod;
        else ret+=dfs(pos-1,sum+i,0,lim&&i==mx),ret%=mod;
    if(!lim&&!fl)f[pos][sum]=ret%mod;
    return ret;
}
int solve(int x){
    len=0;
    while(x)a[++len]=x%10,x/=10;
    return dfs(len,0,1,1)%mod;
}
signed main(){
    int T;scanf("%lld",&T);
    memset(f,-1,sizeof(f));
    while(T--){
        int l,r;
        scanf("%lld%lld",&l,&r);
        printf("%lld\n",((solve(r)-solve(l-1)%mod+mod)%mod));
    }
    return 0;
}
View Code

 AC 自动机 https://www.luogu.com.cn/problem/P5357

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,M=2e6+5;
char s[M];int n,op[N],sum[N];
int tr[N][27],fail[N],tot;
int head[N],nxt[N<<1],to[N<<1],cnt;
void add(int x,int y){
    nxt[++cnt]=head[x];
    head[x]=cnt;
    to[cnt]=y;
}
void ins(char *s,int x){
    int m=strlen(s),p=0;
    for(int i=0;i<m;i++){
        int l=s[i]-'a';
        if(!tr[p][l])tr[p][l]=++tot;
        p=tr[p][l]; 
    }op[x]=p;
}
queue<int>q;
void build_AC(){
    for(int i=0;i<26;i++)
        if(tr[0][i]){
            fail[tr[0][i]]=0;
            q.push(tr[0][i]);
        }
    while(q.size()){
        int u=q.front();q.pop();
        for(int i=0;i<26;i++){
            if(tr[u][i]){
                fail[tr[u][i]]=tr[fail[u]][i];
                q.push(tr[u][i]);
            }
            else tr[u][i]=tr[fail[u]][i];
        }
    }
}
void work(char *s){
    int p=0,m=strlen(s);
    for(int i=0;i<m;i++){
        p=tr[p][s[i]-'a'];
        sum[p]++;
    }
}
void dfs(int u){
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        dfs(v);sum[u]+=sum[v];
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        ins(s,i);    
    }
    build_AC();
    scanf("%s",s);work(s);
    for(int i=1;i<=tot;i++)add(fail[i],i);
    dfs(0);
    for(int i=1;i<=n;i++)printf("%d\n",sum[op[i]]);
    return 0;
}
View Code

 cdq分治斜率优化 https://www.luogu.com.cn/problem/P4655

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
const double INF=1e20;
int h[N],w[N],f[N],s[N],q[N],n;
struct node{int id,x,y,k;}a[N],b[N];
bool operator < (node A,node B){return A.x==B.x?A.y<B.y:A.x<B.x;}
int X(int j){return a[j].x;}
int Y(int j){return a[j].y;}
double slope(int i,int j){
    if(X(i)==X(j))return Y(i)<Y(j)?INF:-INF;
    return double(Y(i)-Y(j))*1.0/(double(X(i)-X(j))*1.0);
}
bool cmp(node A,node B){return A.k<B.k;}
void cdq(int l,int r){
    if(l==r){
        int x=a[l].id;
        a[l].y=f[x]-s[x]+h[x]*h[x];
        return;
    }
    int mid=l+r>>1;
    int L=l,R=mid+1,hd=1,tl=0;
    for(int i=l;i<=r;i++)
        a[i].id<=mid?b[L++]=a[i]:b[R++]=a[i];
    for(int i=l;i<=r;i++)a[i]=b[i];
    cdq(l,mid);
    for(int i=l;i<=mid;i++){
        while(hd<tl&&slope(q[tl-1],q[tl])>=slope(q[tl],i))tl--;
        q[++tl]=i;
    }
    for(int i=mid+1;i<=r;i++){
        while(hd<tl&&slope(q[hd],q[hd+1])<=a[i].k)hd++;
        if(hd<=tl){
            int x=a[i].id,j=q[hd];
            f[x]=min(f[x],a[j].y-a[i].k*a[j].x+s[x-1]+h[x]*h[x]);
        }
    }
    cdq(mid+1,r);
    int j=l-1;
    L=l;R=mid+1;
    while(L<=mid&&R<=r)b[++j]=a[L]<a[R]?a[L++]:a[R++];
    while(L<=mid)b[++j]=a[L++];
    while(R<=r)b[++j]=a[R++];
    for(int i=l;i<=r;i++)a[i]=b[i];
}
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)scanf("%lld",&h[i]);
    for(int i=1;i<=n;i++){
        scanf("%lld",&w[i]);
        s[i]=s[i-1]+w[i];
    }
    for(int i=1;i<=n;i++){
        a[i].id=i;
        a[i].k=2*h[i];
        a[i].x=h[i];
    }
    sort(a+1,a+n+1,cmp);
    memset(f,0x3f,sizeof(f));
    f[1]=0;cdq(1,n);
    printf("%lld\n",f[n]);
    return 0;
}
View Code

 模拟退火 https://www.luogu.com.cn/problem/P1337

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5,MX=RAND_MAX;
const double dt=0.97;
double T,T0;
int n;double ansx,ansy,ans;
struct Node{int x,y,w;}a[N];
double calc(double x,double y){
    double ret=0;
    for(int i=1;i<=n;i++){
        double X=x-a[i].x,Y=y-a[i].y;
        ret+=sqrt(X*X+Y*Y)*(double)a[i].w;
    }return ret;
}
void Anneal(){
    double x=ansx,y=ansy;
    T=2000,T0=1e-15;
    while(T>T0){
        double X=x+double((rand()<<1)-MX)*T;
        double Y=y+double((rand()<<1)-MX)*T;
        double ret=calc(X,Y),delta=ret-ans;
        if(delta<0){x=ansx=X,y=ansy=Y;ans=ret;}
        else if(exp(-delta/T)*MX>rand())x=X,y=Y;
        T*=dt;
    }
}
int main(){
    srand(19260817);
    srand(rand());srand(rand());
    srand(rand());srand(rand());
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
        ansx+=a[i].x,ansy+=a[i].y;
    }
    ansx/=(double)n,ansy/=(double)n;
    ans=calc(ansx,ansy);
    for(int i=1;i<=20;i++)Anneal();    
    return printf("%.3lf %.3lf\n",ansx,ansy)&0;
}
View Code

 高维前缀和 https://www.luogu.com.cn/problem/AT4168

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int n,mx[N],ne[N];
int main(){
    scanf("%d",&n);
    for(int i=0;i<(1<<n);i++)
        scanf("%d",&mx[i]);
    for(int j=0;j<n;j++)
        for(int i=0;i<(1<<n);i++)
            if((i>>j)&1){
                int x=i^(1<<j);
                if(mx[x]>mx[i]){
                    ne[i]=max(mx[i],ne[x]);
                    mx[i]=mx[x];
                }else if(mx[x]==mx[i])
                    ne[i]=mx[i];
                else ne[i]=max(ne[i],mx[x]);
            }
    int ans=0;
    for(int i=1;i<(1<<n);i++){
        ans=max(ans,mx[i]+ne[i]);
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 BSGS https://www.luogu.com.cn/problem/P3846

#include<bits/stdc++.h>
#define int long long
using namespace std;
int p,a,b;
int fpow(int a,int b,int mod){
    int ret=1;
    for(;b;b>>=1){
        if(b&1)ret=1LL*ret*a%mod;
        a=1LL*a*a%mod;
    }return ret;
}
map<int,int>hs;
int bsgs(int a,int b,int p){
    b%=p;int t=sqrt(p)+1;
    for(int i=0;i<t;i++)
        hs[b*fpow(a,i,p)%p]=i;
    a=fpow(a,t,p);
    if(!a)return b==0?1:-1;
    for(int i=1;i<=t;i++){
        int val=fpow(a,i,p);
        int j=hs.find(val)==hs.end()?-1:hs[val];
        if(j>=0&&i*t-j>=0)return i*t-j;
    }return -1;
}
signed main(){
    cin>>p>>a>>b;
    int ans=bsgs(a,b,p);
    if(ans==-1)puts("no solution");
    else cout<<ans<<endl;
    return 0;
}
View Code

EXCRT CRT https://www.luogu.com.cn/problem/P4777

#include<bits/stdc++.h>
#define int long long
using namespace std;
int mul(int a,int b,int mod){
    int ret=0;
    for(;b;b>>=1){
        if(b&1)(ret+=a)%=mod;
        (a*=2)%=mod;
    }return ret;
}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
void exgcd(int a,int b,int &x,int &y){
    if(b==0){x=1,y=0;return;}
    exgcd(b,a%b,y,x),y-=a/b*x;
}
signed main(){
    int n,a,b,c,d;
    cin>>n>>a>>b;
    for(int i=2;i<=n;i++){
        cin>>c>>d;
        int dt=((d-b)%c+c)%c,D=gcd(a,c),L=a/D*c,x=0,y=0;
        exgcd(a,c,x,y);x=mul(x,dt/D,c/D);
        b=(b+a*x)%L;a=L;
    }
    return cout<<((b%a)+a)%a<<endl,0;
}
View Code

 李超线段树 https://www.luogu.com.cn/problem/CF932F

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=4.1e5+5,DT=1e5+5,MX=DT<<1,INF=1e15;
vector<int>G[N];
int t[N<<4],ls[N<<4],rs[N<<4],rt[N<<4],cnt;
int k[N],b[N],A[N],B[N],f[N],n;
int w(int p,int x){return k[p]*x+b[p];}
void update(int &p,int l,int r,int x){
    if(!p){p=++cnt;t[p]=x;return;}
    int mid=l+r>>1;
    if(w(t[p],mid)>w(x,mid))swap(t[p],x);
    if(w(t[p],l)<=w(x,l)&&w(t[p],r)<=w(x,r))return;
    if(w(t[p],l)>w(x,l))update(ls[p],l,mid,x);
    else update(rs[p],mid+1,r,x);
}
int query(int p,int l,int r,int x){
    if(!p)return INF;
    if(l==r)return w(t[p],x);
    int mid=l+r>>1;int ret=w(t[p],x);
    if(x<=mid)ret=min(ret,query(ls[p],l,mid,x));
    else ret=min(ret,query(rs[p],mid+1,r,x));
    return ret;
}
int merge(int p,int q,int l,int r){
    if(!p||!q)return p|q;
    update(p,l,r,t[q]);
    int mid=l+r>>1;
    ls[p]=merge(ls[p],ls[q],l,mid);
    rs[p]=merge(rs[p],rs[q],mid+1,r);
    return p;
}
void dfs(int u,int fa){
    for(auto v:G[u]){
        if(v==fa)continue;dfs(v,u);
        rt[u]=merge(rt[u],rt[v],1,MX);
    }
    f[u]=query(rt[u],1,MX,A[u]+DT);
    if(f[u]==INF)f[u]=0;
    k[u]=B[u];b[u]=f[u]-B[u]*DT;
    update(rt[u],1,MX,u);
}
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)scanf("%lld",&A[i]);
    for(int i=1;i<=n;i++)scanf("%lld",&B[i]);
    for(int i=1,u,v;i<n;i++){
        scanf("%lld%lld",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }dfs(1,0);
    for(int i=1;i<=n;i++)printf("%lld ",f[i]);
    return puts("")&0;
}
View Code

 有源汇上下界最大流

int work(int s,int t){
    S=N-1,T=N-2;
    for(int i=1;i<=m;i++){
        w[e[i].x]-=e[i].dn;
        w[e[i].y]+=e[i].dn;
        add(e[i].x,e[i].y,e[i].up-e[i].dn);
    }
    int sum=0;
    for(int i=1;i<=n;i++)
        if(w[i]>0)add(S,i,w[i]),sum+=w[i];
        else if(w[i]<0)add(i,T,-w[i]);
    add(t,s,INF);
    int ret=dinic();
    if(ret!=sum)return -1;
    int ans=edge[tot];
    edge[tot]=edge[tot^1]=0;
    S=s;T=t;
    return ans+dinic();
}
View Code

 有源汇上下界最小流

int work(int s,int t){
    S=N-1,T=N-2;
    for(int i=1;i<=m;i++){
        w[e[i].x]-=e[i].dn;
        w[e[i].y]+=e[i].dn;
        add(e[i].x,e[i].y,e[i].up-e[i].dn);
    }
    int sum=0;
    for(int i=1;i<=n;i++)
        if(w[i]>0)add(S,i,w[i]),sum+=w[i];
        else if(w[i]<0)add(i,T,-w[i]);
    add(t,s,INF);
    int ret=dinic();
    if(ret!=sum)return -1;
    int ans=edge[tot];
    edge[tot]=edge[tot^1]=0;
    S=t;T=s;
    return ans-dinic();
}
View Code

 珂朵莉树 https://codeforces.com/problemset/problem/896/C

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=1e9+7,N=1e5+5;
int a[N];
int fpow(int a,int b,int P){
    int ret=1;a%=P;
    for(;b;b>>=1){
        if(b&1)ret=1LL*ret*a%P;
        a=1LL*a*a%P;
    }return ret;
}
struct Node{
    int l,r;
    mutable int v;
    Node(){l=r=v=0;}
    Node(int L,int R,int V){l=L;r=R;v=V;}
    bool operator<(const Node &a)const{return l<a.l;}
};
set<Node>s;
set<Node>::iterator split(int pos){
    set<Node>::iterator it=s.lower_bound(Node(pos,0,0));
    if(it!=s.end()&&it->l==pos)return it;
    it--;if(it->r<pos)return s.end();
    int l=it->l,r=it->r,v=it->v;
    s.erase(it);s.insert(Node(l,pos-1,v));
    return s.insert(Node(pos,r,v)).first;
}
void assign(int l,int r,int x){
    set<Node>::iterator itr=split(r+1),itl=split(l);
    s.erase(itl,itr);
    s.insert(Node(l,r,x));
}
void add(int l,int r,int x){
    set<Node>::iterator itr=split(r+1),itl=split(l);
    for(set<Node>::iterator it=itl;it!=itr;it++)
        it->v+=x;
}
struct Fuck{int x,y;}tmp[N];
bool cmp(Fuck a,Fuck b){return a.x<b.x;}
int kth(int l,int r,int x){
    set<Node>::iterator itr=split(r+1),itl=split(l);
    int tot=0;
    for(set<Node>::iterator it=itl;it!=itr;it++)
        tmp[++tot].x=it->v,tmp[tot].y=it->r-it->l+1;
    sort(tmp+1,tmp+tot+1,cmp);
    int k=0;
    for(int i=1;i<=tot;i++)
        if((k+=tmp[i].y)>=x)return tmp[i].x;
}
int ans(int l,int r,int x,int y){
    set<Node>::iterator itr=split(r+1),itl=split(l);
    int ret=0;
    for(set<Node>::iterator it=itl;it!=itr;it++)
        ret=(ret+1LL*(it->r-it->l+1)%y*fpow(it->v,x,y)%y)%y;
    return ret;
}
int n,m,seed,vmax;
int rnd(){
    int ret=seed;
    seed=(seed*7+13)%MOD;
    return ret;
}
signed main(){
    cin>>n>>m>>seed>>vmax;
    for(int i=1;i<=n;i++){
        a[i]=rnd()%vmax+1;
        s.insert(Node(i,i,a[i]));
    }
    while(m--){
        int op,l,r,x,y;
        op=(rnd()%4)+1;
        l=(rnd()%n)+1,r=(rnd()%n)+1;
        if(l>r)swap(l,r);
        if(op==3)x=rnd()%(r-l+1)+1;
        else x=rnd()%vmax+1;
        if(op==4)y=rnd()%vmax+1;
        if(op==1)add(l,r,x);
        else if(op==2)assign(l,r,x); 
        else if(op==3)printf("%lld\n",kth(l,r,x));
        else printf("%lld\n",ans(l,r,x,y));
    }
    return 0;
}
View Code

 Min_25筛 https://www.luogu.com.cn/problem/P5325

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7,N=2e5+5;
int iv2,iv6,T,n;
int v[N],p[N],cnt;
int id1[N],id2[N],sp1[N],sp2[N],g1[N],g2[N];
int w[N],tot;
int fpow(int a,int b){
    int ret=1;
    for(;b;b>>=1){
        if(b&1)ret=ret*a%mod;
        a=a*a%mod;
    }return ret;
}
long long S(int x,int y){
    if(p[y]>=x)return 0;
    int k=x<=T?id1[x]:id2[n/x];
    int ans=(g2[k]-g1[k]-(sp2[y]-sp1[y]))%mod;
    for(int i=y+1;i<=cnt&&p[i]*p[i]<=x;i++){
        int pe=p[i];
        for(int e=1;pe<=x;e++,pe=pe*p[i])
            (ans+=pe%mod*((pe%mod-1)%mod)%mod*(S(x/pe,i)+(e!=1))%mod)%=mod;
    }return ans;
}
signed main(){
    iv2=fpow(2,mod-2);iv6=fpow(6,mod-2);
    cin>>n;T=sqrt(n);
    for(int i=2;i<=T;i++){
        if(!v[i])v[i]=i,p[++cnt]=i;
        for(int j=1;j<=cnt;j++){
            if(p[j]>v[i]||p[j]>T/i)break;
            v[i*p[j]]=p[j];
        }
    }
    for(int i=1;i<=cnt;i++){
        sp1[i]=(sp1[i-1]+p[i])%mod;
        sp2[i]=(sp2[i-1]+p[i]*p[i]%mod)%mod;
    }
    for(int l=1,r=0;l<=n;l=r+1){
        r=n/(n/l);w[++tot]=n/l;
        g1[tot]=w[tot]%mod;
        g2[tot]=g1[tot]*(g1[tot]+1)%mod*(2*g1[tot]%mod+1)%mod*iv6%mod;(g2[tot]-=1)%=mod;
        g1[tot]=g1[tot]*(g1[tot]+1)%mod*iv2%mod;(g1[tot]-=1)%=mod;
        if(n/l<=T)id1[n/l]=tot;
        else id2[n/(n/l)]=tot;
    }
    for(int i=1;i<=cnt;i++)
        for(int j=1;j<=tot&&p[i]*p[i]<=w[j];j++){
            int k=w[j]/p[i]<=T?id1[w[j]/p[i]]:id2[n/(w[j]/p[i])];
            (g1[j]-=p[i]*(g1[k]-sp1[i-1])%mod)%=mod;
            (g2[j]-=p[i]*p[i]%mod*(g2[k]-sp2[i-1])%mod)%=mod;
        }
    cout<<((S(n,0)+1)+mod)%mod<<endl;
    return 0;
}
View Code

杜教筛 https://www.luogu.com.cn/problem/P4213

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6;
int mu[N+5],phi[N+5];
int v[N+5],p[N+5],m;
map<int,int>Ans1,Ans2;
int sum1[N+5],sum2[N+5];
void prework(int n){
    memset(v,m=0,sizeof(v));
    phi[1]=mu[1]=1;
    for(int i=2;i<=n;i++){
        if(v[i]==0){
            v[i]=i,p[++m]=i;
            phi[i]=i-1;mu[i]=-1;
        }
        for(int j=1;j<=m;j++){
            if(p[j]>v[i]||p[j]>n/i)break;
            v[i*p[j]]=p[j];
            if(i%p[j])mu[i*p[j]]=-mu[i],phi[i*p[j]]=phi[i]*(p[j]-1);
            else {mu[i*p[j]]=0;phi[i*p[j]]=phi[i]*p[j];}
        }
    }
    sum1[0]=sum2[0]=0;
//    cout<<"NMSL  "<<sum2[0]<<' '<<phi[1]<<endl;
    for(int i=1;i<=n;i++)sum1[i]=sum1[i-1]+mu[i];
    for(int i=1;i<=n;i++){
        sum2[i]=sum2[i-1]+phi[i];
//        cout<<i<<" : "<<sum2[i]<<endl;system("pause");
    }
}
int get_mu(int x){
    if(x<=N)return sum1[x];
    if(Ans1[x])return Ans1[x];
    int ans=1;
    for(int l=2,r;l<=x;l=r+1){
        r=x/(x/l);
        ans-=(r-l+1)*get_mu(x/l);
    }
    return Ans1[x]=ans;
}
int get_phi(int x){
    if(x<=N)return sum2[x];
    if(Ans2[x])return Ans2[x];
    int ans=x*(x+1)>>1;
    for(int l=2,r;l<=x;l=r+1){
        r=x/(x/l);
        ans-=(r-l+1)*get_phi(x/l);
    }
    return Ans2[x]=ans;
}
signed main(){
    prework(N);int T;
    scanf("%lld",&T);
    while(T--){
        int n;scanf("%lld",&n);
        printf("%lld %lld\n",get_phi(n),get_mu(n));
    }
    return 0;
}
View Code

 Miller Rabin https://www.luogu.com.cn/problem/SP288

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int p[12]={2,3,5,7,11,13,17,19,23,29,31,37};
int fmul(int a,int b,int mod){
    int ret=0;
    for(;b;b>>=1){
        if(b&1)ret=(ret+a)%mod;
        a=a*2%mod;
    }return ret;
}
int fpow(int a,int b,int mod){
    int ret=1;
    for(;b;b>>=1){
        if(b&1)ret=fmul(ret,a,mod);
        a=fmul(a,a,mod);
    }return ret;
}
bool ck(int n,int m){
    int sum=0,d=n-1;
    while(!(d&1))d>>=1,sum++;
    int z=fpow(m,d,n);
    if(!(z-1))return 1;
    for(int i=0;i<sum;i++){
        if(z==n-1)return 1;
        z=fmul(z,z,n);
    }return 0;
}
bool Miller_Rabin(int n){
    if(n<2)return 0;
    for(int i=0;i<12;i++){
        if(p[i]==n)return 1;
        if(n%p[i]==0)return 0;
        if(!ck(n,p[i]))return 0;
    }return 1;
}
signed main(){
    int T;cin>>T;
    while(T--){
        int n;cin>>n;
        puts(Miller_Rabin(n)?"YES":"NO");
    }return 0;
}
View Code

 Pollard Rho https://www.luogu.com.cn/problem/P4718

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define lll __int128
const int p[12]={2,3,5,7,11,13,17,19,23,29,31,37};
int ans;
const int M=(1LL<<7)-1;
int fmul(int a,int b,int mod){
    int ret=0;
    for(;b;b>>=1){
        if(b&1)ret=(ret+a)%mod;
        a=a*2%mod;
    }return ret;
}
int fpow(int a,int b,int mod){
    int ret=1;
    for(;b;b>>=1){
        if(b&1)ret=fmul(ret,a,mod);
        a=fmul(a,a,mod);
    }return ret;
}
bool ck(int n,int m){
    int sum=0,d=n-1;
    while(!(d&1))d>>=1,sum++;
    int z=fpow(m,d,n);
    if(!(z-1))return 1;
    for(int i=0;i<sum;i++){
        if(z==n-1)return 1;
        z=fmul(z,z,n);
    }return 0;
}
bool Miller_Rabin(int n){
    if(n<2)return 0;
    for(int i=0;i<12;i++){
        if(p[i]==n)return 1;
        if(n%p[i]==0)return 0;
        if(!ck(n,p[i]))return 0;
    }return 1;
}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int G(int x,int n,int c){return ((lll)x*x+c)%n;}
int rd(){return rand()*rand();}
int Pollard_Rho(int n){
    if(n%2==0)return 2;
    if(n%3==0)return 3;
    int pr=0,x=0,q=1,t=1,c=rd()%(n-1)+1;
    for(int k=1;;k<<=1,pr=x,q=1){
        for(int i=1;i<=k;i++){
            x=G(x,n,c),q=(lll)q*abs(x-pr)%n;
            if(!(i%M)){t=gcd(q,n);if(t>1)return t;}
        }
        if(t>1||(t=gcd(q,n))>1)return t;
    }
}
void find(int x){
    if(x<=1||x<=ans)return;
    if(Miller_Rabin(x))return ans=max(ans,x),void();
    int p=x;
    while(p>=x)p=Pollard_Rho(x);
    while(x%p==0)x/=p;
    find(x);find(p);
}
signed main(){
    srand(time(0));
    int T;cin>>T;
    double st=clock();
    while(T--){
        int n;ans=0;cin>>n;find(n);
        if(ans==n)puts("Prime");
        else cout<<ans<<endl;
    }
    return 0;
}
View Code
posted @ 2020-10-24 15:44  Isenthalpic  阅读(37)  评论(0)    收藏  举报