数据结构模板整理

过滤一些较简单的如线段树、树状数组等,甚至树链剖分都被过滤了。

 左偏树https://www.luogu.org/problemnew/show/P3377

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+7;
int n,Q,fa[N],lc[N],rc[N],w[N],d[N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int merge(int x,int y)
{
    if(!x||!y)return x+y;
    if(w[x]>w[y]||w[x]==w[y]&&x>y)swap(x,y);
    rc[x]=merge(rc[x],y);
    if(d[lc[x]]<d[rc[x]])swap(lc[x],rc[x]);
    d[x]=d[rc[x]]+1;
    return x;
}
int main()
{
    scanf("%d%d",&n,&Q);
    for(int i=1;i<=n;i++)scanf("%d",&w[i]),fa[i]=i;
    d[0]=-1;
    while(Q--)
    {
        int op,x,y;scanf("%d%d",&op,&x);
        if(op==1)
        {
            scanf("%d",&y);
            if(w[x]==-1||w[y]==-1)continue;
            int u=find(x),v=find(y);
            if(u!=v)fa[u]=fa[v]=merge(u,v);
        }
        else{
            if(w[x]==-1){puts("-1");continue;}
            y=find(x);
            printf("%d\n",w[y]);
            w[y]=-1,fa[y]=merge(lc[y],rc[y]),fa[fa[y]]=fa[y];
        }
    }
}

主席树https://www.luogu.org/problemnew/show/P3834

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+7;
int n,Q,cnt,m,a[N],b[N],root[N],sum[N*30],lc[N*30],rc[N*30];
int build(int l,int r)
{
    int rt=++cnt,mid=(l+r)/2;
    sum[rt]=0;
    if(l<r)lc[rt]=build(l,mid),rc[rt]=build(mid+1,r);
    return rt;
}
int update(int prt,int l,int r,int k)
{
    int rt=++cnt,mid=(l+r)/2;
    lc[rt]=lc[prt];rc[rt]=rc[prt];sum[rt]=sum[prt]+1;
    if(l==r)return rt;
    if(k<=mid)lc[rt]=update(lc[prt],l,mid,k);
    else rc[rt]=update(rc[prt],mid+1,r,k);
    return rt;
}
int query(int L,int R,int l,int r,int k)
{
    if(l>=r)return l;
    int x=sum[lc[R]]-sum[lc[L]],mid=(l+r)/2;
    if(x>=k)return query(lc[L],lc[R],l,mid,k);
    return query(rc[L],rc[R],mid+1,r,k-x);
}
int main()
{
    scanf("%d%d",&n,&Q);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+n+1);
    m=unique(b+1,b+n+1)-b-1;
    for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+m+1,a[i])-b;
    root[0]=build(1,m);
    for(int i=1;i<=n;i++)root[i]=update(root[i-1],1,m,a[i]);
    while(Q--)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        printf("%d\n",b[query(root[x-1],root[y],1,m,z)]);
    }
}

可持久化并查集https://www.luogu.org/problemnew/show/P3402

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int n,m,tot,root[N],fa[N*30],dep[N*30],lc[N*30],rc[N*30];
void build(int&rt,int l,int r)
{
    rt=++tot;
    if(l==r){fa[rt]=l;return;}
    int mid=(l+r)/2;
    build(lc[rt],l,mid);
    build(rc[rt],mid+1,r);
}
void update(int&rt,int prt,int l,int r,int pos,int f)
{
    rt=++tot;
    if(l==r){fa[rt]=f,dep[rt]=dep[prt];return;}
    lc[rt]=lc[prt],rc[rt]=rc[prt];
    int mid=(l+r)/2;
    if(pos<=mid)update(lc[rt],lc[prt],l,mid,pos,f);
    else update(rc[rt],rc[prt],mid+1,r,pos,f);
}
int query(int rt,int l,int r,int pos)
{
    if(l==r)return rt;
    int mid=(l+r)/2;
    if(pos<=mid)return query(lc[rt],l,mid,pos);
    return query(rc[rt],mid+1,r,pos);
}
int find_fa(int rt,int x)
{
    int y=query(rt,1,n,x);
    if(x==fa[y])return y;
    return find_fa(rt,fa[y]);
}
void add(int rt,int l,int r,int pos)
{
    if(l==r){dep[rt]++;return;}
    int mid=(l+r)/2;
    if(pos<=mid)add(lc[rt],l,mid,pos);
    else add(rc[rt],mid+1,r,pos);
}
int main()
{
    scanf("%d%d",&n,&m);
    build(root[0],1,n);
    for(int i=1,op,x,y;i<=m;i++)
    {
        scanf("%d%d",&op,&x);
        if(op==1)
        {
            scanf("%d",&y);
            root[i]=root[i-1];
            x=find_fa(root[i],x);
            y=find_fa(root[i],y);
            if(fa[x]==fa[y])continue;
            if(dep[x]>dep[y])swap(x,y);
            update(root[i],root[i-1],1,n,fa[x],fa[y]);
            if(dep[x]==dep[y])add(root[i],1,n,fa[y]);
        }
        else if(op==2)root[i]=root[x];
        else{
            scanf("%d",&y);
            root[i]=root[i-1];
            x=find_fa(root[i],x);
            y=find_fa(root[i],y);
            if(fa[x]==fa[y])puts("1");else puts("0");
        }
    }
}

线段树合并https://www.lydsy.com/JudgeOnline/problem.php?id=2212

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e6+77;
int n,lc[N],rc[N],cnt[N],tot=0;
ll ans;
int merge(int rt1,int rt2,int l,int r,ll&s1,ll&s2)
{
    if(!rt1||!rt2)return rt1+rt2;
    if(l==r){cnt[rt1]+=cnt[rt2];return rt1;}
    int mid=(l+r)/2;
    s1+=1ll*cnt[rc[rt1]]*cnt[lc[rt2]];
    s2+=1ll*cnt[rc[rt2]]*cnt[lc[rt1]];
    lc[rt1]=merge(lc[rt1],lc[rt2],l,mid,s1,s2);
    rc[rt1]=merge(rc[rt1],rc[rt2],mid+1,r,s1,s2);
    cnt[rt1]=cnt[lc[rt1]]+cnt[rc[rt1]];
    return rt1;
}
int build(int l,int r,int k)
{
    int x=++tot;
    if(l==r){cnt[x]=1;return x;}
    int mid=(l+r)/2;
    if(k<=mid)lc[x]=build(l,mid,k);
    else rc[x]=build(mid+1,r,k);
    cnt[x]=cnt[lc[x]]+cnt[rc[x]];
    return x;
}
int dfs()
{
    int x;
    scanf("%d",&x);
    if(x)return build(1,n,x);
    ll s1=0,s2=0;
    int u=dfs(),v=dfs(),rt=merge(u,v,1,n,s1,s2);
    ans+=min(s1,s2);
    return rt;
}
int main()
{
    scanf("%d",&n);
    dfs();
    printf("%lld",ans);
}

树上启发式合并https://www.luogu.org/problemnew/show/P3302

#include<bits/stdc++.h>
using namespace std;
const int N=80100;
int n,m,p,a[N],b[N],rt[N],sz[N],fa[N],dep[N],f[N][20];
vector<int>G[N];
namespace tree{
    struct seg{int lc,rc,s;}tr[N*400];
    int sz;
    void update(int k,int l,int r,int&rt,int prt)
    {
        tr[rt=++sz]=tr[prt],tr[rt].s++;
        if(l==r)return;
        int mid=l+r>>1;
        if(k<=mid)update(k,l,mid,tr[rt].lc,tr[prt].lc);
        else update(k,mid+1,r,tr[rt].rc,tr[prt].rc);
    }
    int query(int u,int v,int pu,int pv,int k,int l,int r)
    {
        if(l==r)return l;
        int mid=l+r>>1,sum=tr[tr[u].lc].s+tr[tr[v].lc].s-tr[tr[pu].lc].s-tr[tr[pv].lc].s;
        if(k<=sum)return query(tr[u].lc,tr[v].lc,tr[pu].lc,tr[pv].lc,k,l,mid);
        return query(tr[u].rc,tr[v].rc,tr[pu].rc,tr[pv].rc,k-sum,mid+1,r);
    }
}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void dfs(int u,int Fa,int anc)
{
    f[u][0]=Fa;
    for(int i=1;i<=19;i++)f[u][i]=f[f[u][i-1]][i-1];
    sz[anc]++,dep[u]=dep[Fa]+1,fa[u]=Fa;
    int x=lower_bound(b+1,b+p+1,a[u])-b;
    tree::update(x,1,p,rt[u],rt[Fa]);
    for(int i=0;i<G[u].size();i++)if(G[u][i]!=Fa)dfs(G[u][i],u,anc);
}
int lca(int x,int y)
{
    if(dep[x]<dep[y])swap(x,y);
    int t=dep[x]-dep[y];
    for(int i=0;(1<<i)<=t;i++)if(t&(1<<i))x=f[x][i];
    if(x==y)return x;
    for(int i=19;~i;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    return f[x][0];
}
int main()
{
    int Q;scanf("%*d%d%d%d",&n,&m,&Q);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i],fa[i]=i;
    for(int i=1,x,y;i<=m
    ;i++)scanf("%d%d",&x,&y),G[x].push_back(y),G[y].push_back(x);
    sort(b+1,b+n+1);
    p=unique(b+1,b+n+1)-b-1;
    for(int i=1;i<=n;i++)if(!dep[i])dfs(i,0,i),fa[i]=i;
    char op;
    int x,y,z,ans=0;
    while(Q--)
    {
        scanf(" %c%d%d",&op,&x,&y),x^=ans,y^=ans;
        if(op=='Q')
        {
            scanf("%d",&z),z^=ans;
            int Fa=lca(x,y);
            printf("%d\n",ans=b[tree::query(rt[x],rt[y],rt[Fa],rt[f[Fa][0]],z,1,p)]);
        }
        else{
            G[x].push_back(y),G[y].push_back(x);
            int fx=find(x),fy=find(y);
            if(sz[fx]<sz[fy])swap(x,y),swap(fx,fy);
            dfs(y,x,fx);
        }
    }
}

可持久化Triehttps://www.luogu.org/problemnew/show/P4098

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>pii;
const int N=50005;
int n,cnt,ans,a[N],rt[N],ch[N*32][2],sz[N*32],L[N],R[N];
pii b[N];
void build(int x,int id)
{
    int u,v=rt[id-1];u=rt[id]=++cnt;
    sz[u]=sz[v]+1;
    for(int i=29;~i;i--)
    {
        int c=x>>i&1;
        ch[u][c^1]=ch[v][c^1],ch[u][c]=++cnt;
        u=ch[u][c],v=ch[v][c],sz[u]=sz[v]+1;
    }
}
int query(int x,int l,int r)
{
    if(l>r)return 0;
    l=rt[l-1],r=rt[r];
    int ret=0;
    for(int i=29;~i;i--)
    {
        int c=x>>i&1;
        if(sz[ch[r][c^1]]-sz[ch[l][c^1]])ret+=1<<i,l=ch[l][c^1],r=ch[r][c^1];
        else l=ch[l][c],r=ch[r][c];
    }
    return ret;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),build(a[i],i),b[i]=pii(a[i],i),L[i]=i-1,R[i]=i+1;
    sort(b+1,b+n+1);
    for(int i=1;i<=n;i++)
    {
        int x=b[i].second,l=L[x],r=R[x];L[r]=l,R[l]=r;
        if(l)ans=max(ans,query(a[x],L[l]+1,r-1));
        if(r)ans=max(ans,query(a[x],l+1,R[r]-1));
    }
    printf("%d",ans);
}

动态开点线段树https://www.lydsy.com/JudgeOnline/problem.php?id=3939

#include<bits/stdc++.h>
#define lson l,mid,lc[rt]
#define rson mid+1,r,rc[rt]
using namespace std;
const int N=760,M=N*N*15,mod=1e9+7;
int n,m,k,cnt,a[N][N],f[N][N],s[N][N],sum[M],root[N*N],lc[M],rc[M];
void insert(int k,int c,int l,int r,int &rt)
{
    if(!rt)rt=++cnt;
    if(l==r){sum[rt]=(sum[rt]+c)%mod;return;}
    int mid=(l+r)/2;
    if(k<=mid)insert(k,c,lson);
    else insert(k,c,rson);
    sum[rt]=(sum[lc[rt]]+sum[rc[rt]])%mod;
}
int query(int L,int R,int l,int r,int rt)
{
    if(!rt)return 0;
    if(L<=l&&r<=R)return sum[rt];
    int mid=(l+r)/2,ret=0;
    if(L<=mid)ret+=query(L,R,lson);
    if(R>mid)ret=(ret+query(L,R,rson))%mod;
    return ret;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    scanf("%d",&a[i][j]);
    f[1][1]=1;
    for(int i=1;i<=m;i++)s[1][i]=1;
    for(int i=2;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        f[i][j]=s[i-1][j-1];
        if(j>1)f[i][j]=(f[i][j]-query(1,j-1,1,m,root[a[i][j]])+mod)%mod;
        s[i][j]=(1ll*s[i][j-1]+s[i-1][j]-s[i-1][j-1]+f[i][j]+mod)%mod;
        insert(j,f[i-1][j],1,m,root[a[i-1][j]]);
    }
    printf("%d",f[n][m]);
}

treaphttps://www.luogu.org/problemnew/show/P3369

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int n,cnt,root,ans,lc[N],rc[N],sz[N],w[N],rnd[N],v[N];
void update(int rt){sz[rt]=sz[lc[rt]]+sz[rc[rt]]+w[rt];}
void rturn(int&rt)
{
    int t=lc[rt];
    lc[rt]=rc[t];rc[t]=rt;
    sz[t]=sz[rt];update(rt);rt=t;
}
void lturn(int&rt)
{
    int t=rc[rt];
    rc[rt]=lc[t];lc[t]=rt;
    sz[t]=sz[rt];update(rt);rt=t;
}
void insert(int&rt,int val)
{
    if(!rt)
    {
        rt=++cnt;
        sz[rt]=w[rt]=1;
        v[rt]=val;rnd[rt]=rand();
        return;
    }
    sz[rt]++;
    if(v[rt]==val)w[rt]++;
    else if(v[rt]>val){insert(lc[rt],val);if(rnd[lc[rt]]<rnd[rt])rturn(rt);}
    else{insert(rc[rt],val);if(rnd[rc[rt]]<rnd[rt])lturn(rt);}
}
void del(int&rt,int val)
{
    if(!rt)return;
    if(v[rt]==val)
    {
        if(w[rt]>1){w[rt]--;sz[rt]--;return;}
        if(lc[rt]*rc[rt]==0)rt=lc[rt]+rc[rt];
        else if(rnd[lc[rt]]<rnd[rc[rt]])rturn(rt),del(rt,val);
        else lturn(rt),del(rt,val);
        return;
    }
    sz[rt]--;
    if(v[rt]>val)del(lc[rt],val);
    else del(rc[rt],val);
}
int query_rank(int rt,int val)
{
    if(!rt)return 0;
    if(v[rt]==val)return sz[lc[rt]]+1;
    if(v[rt]>val)return query_rank(lc[rt],val);
    return sz[lc[rt]]+w[rt]+query_rank(rc[rt],val);
}
int query_num(int rt,int rnk)
{
    if(!rt)return 0;
    if(rnk<=sz[lc[rt]])return query_num(lc[rt],rnk);
    if(rnk>sz[lc[rt]]+w[rt])return query_num(rc[rt],rnk-sz[lc[rt]]-w[rt]);
    return v[rt];
}
void query_pre(int rt,int val)
{
    if(!rt)return;
    if(v[rt]<val)ans=rt,query_pre(rc[rt],val);
    else query_pre(lc[rt],val);
}
void query_sub(int rt,int val)
{
    if(!rt)return;
    if(v[rt]>val)ans=rt,query_sub(lc[rt],val);
    else query_sub(rc[rt],val);
}
int main()
{
    srand(time(0));
    scanf("%d",&n);
    for(int i=1,op,x;i<=n;i++)
    {
        scanf("%d%d",&op,&x);
        if(op==1)insert(root,x);
        if(op==2)del(root,x);
        if(op==3)printf("%d\n",query_rank(root,x));
        if(op==4)printf("%d\n",query_num(root,x));
        if(op==5)ans=0,query_pre(root,x),printf("%d\n",v[ans]);
        if(op==6)ans=0,query_sub(root,x),printf("%d\n",v[ans]);
    }
}

splayhttps://www.luogu.org/problemnew/show/P3391

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int n,m,root,sz[N],fa[N],ch[N][2];
bool rev[N];
void pushup(int rt){sz[rt]=sz[ch[rt][0]]+sz[ch[rt][1]]+1;}
void pushdown(int rt)
{
    if(rev[rt])
    {
        swap(ch[rt][0],ch[rt][1]);
        rev[rt]=0;
        rev[ch[rt][0]]^=1,rev[ch[rt][1]]^=1;
    }
}
void rotate(int&rt,int x)
{
    int y=fa[x],z=fa[y];
    bool dy=ch[y][1]==x,dz=ch[z][1]==y;
    pushdown(y);
    if(y==rt)rt=x;else ch[z][dz]=x;
    fa[x]=z;
    ch[y][dy]=ch[x][dy^1],fa[ch[x][dy^1]]=y;
    ch[x][dy^1]=y,fa[y]=x;
    pushup(y);
}
void splay(int&rt,int x)
{
    pushdown(x);
    while(x!=rt)
    {
        int y=fa[x],z=fa[y];
        if(y!=rt)
        {
            if((ch[y][1]==x)^(ch[z][1]==y))rotate(rt,x);
            else rotate(rt,y);
        }
        rotate(rt,x);
    }
    pushup(x);
}
int find(int rt,int x)
{
    if(!rt)return 0;
    pushdown(rt);
    if(x<=sz[ch[rt][0]])return find(ch[rt][0],x);
    if(x==sz[ch[rt][0]]+1)return rt;
    return find(ch[rt][1],x-sz[ch[rt][0]]-1);
}
void print(int rt)
{
    if(!rt)return;
    pushdown(rt);
    print(ch[rt][0]);
    if(rt>1&&rt<n+2)printf("%d ",rt-1);
    print(ch[rt][1]);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n+2;++i)sz[i]=n+3-i,fa[i]=i-1,ch[i][1]=i+1;
    ch[n+2][1]=0,root=1;
    while(m--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        splay(root,find(root,l));
        splay(ch[root][1],find(root,r+2));
        rev[ch[ch[root][1]][0]]^=1;
    }
    print(root);
}

替罪羊树https://www.lydsy.com/JudgeOnline/problem.php?id=3065

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=71000,M=1e7+7;
const double alpha=0.75;
int n,m,sz,ans,root,tmp,v[N],dfn[N],rt[N],lc[N],rc[N];
struct seg{int l,r,sum;}a[M];
vector<int>rec,t,p;
int newnode()
{
    if(!rec.size())return++sz;
    int k=rec.back();rec.pop_back();
    return k;
}
void reclaim(int&x)
{
    if(!x)return;
    rec.pb(x);
    reclaim(a[x].l);reclaim(a[x].r);
    a[x].sum=0;x=0;
}
void insert(int &k,int l,int r,int p,int v)
{
    if(!k)k=newnode();
    if(l==r){a[k].sum+=v;return;}
    int mid=(l+r)/2;
    if(p<=mid)insert(a[k].l,l,mid,p,v);
    else insert(a[k].r,mid+1,r,p,v);
    a[k].sum=a[a[k].l].sum+a[a[k].r].sum;
    if(!a[k].sum)reclaim(k);
}
void build(int &k,int l,int r)
{
    if(l>r)return;
    if(l==r)
    {
        k=dfn[l];insert(rt[k],0,70000,v[k],1);return;
    }
    int mid=(l+r)/2;k=dfn[mid];
    build(lc[k],l,mid-1);build(rc[k],mid+1,r);
    for(int i=l;i<=r;i++)insert(rt[k],0,70000,v[dfn[i]],1);
}
void del(int &x)
{
    if(!x)return;reclaim(rt[x]);
    del(lc[x]);p.pb(x);del(rc[x]);
    x=0;
}
void rebuild(int&x)
{
    del(x);
    int s1=p.size();
    for(int i=1;i<=s1;i++)dfn[i]=p[i-1];
    build(x,1,s1);
    p.clear();
}
int update(int k,int x,int val)
{
    insert(rt[k],0,70000,val,1);
    int t,L=a[rt[lc[k]]].sum;
    if(L+1==x)t=v[k],v[k]=val;
    else if(L>=x)t=update(lc[k],x,val);
    else t=update(rc[k],x-L-1,val);
    insert(rt[k],0,70000,t,-1);
    return t;
}
void query(int k,int l,int r)
{
    int L=a[rt[lc[k]]].sum,R=a[rt[k]].sum;
    if(l==1&&r==R){t.pb(rt[k]);return;}
    if(l<=L+1&&L+1<=r)p.pb(v[k]);
    if(r<=L)query(lc[k],l,r);
    else if(l>L+1)query(rc[k],l-L-1,r-L-1);
    else{
        if(l<=L)query(lc[k],l,L);
        if(R>L+1)query(rc[k],1,r-L-1);
    }
}
int solve(int L,int R,int k)
{
    query(root,L,R);
    k--;
    int l=0,r=70000,s1=t.size(),s2=p.size();
    while(l<r)
    {
        int mid=(l+r)/2,sum=0;
        for(int i=0;i<s1;i++)sum+=a[a[t[i]].l].sum;
        for(int i=0;i<s2;i++)if(p[i]>=l&&p[i]<=mid)sum++;
        if(k<sum)
        {
            for(int i=0;i<s1;i++)t[i]=a[t[i]].l;
            r=mid;
        }
        else{
            for(int i=0;i<s1;i++)t[i]=a[t[i]].r;
            l=mid+1;k-=sum;
        }
    }
    t.clear();p.clear();
    return l;
}
void insert(int&k,int x,int val)
{
    if(!k)
    {
        k=++n;
        insert(rt[k],0,70000,val,1);
        v[k]=val;
        return;
    }
    insert(rt[k],0,70000,val,1);
    int L=a[rt[lc[k]]].sum;
    if(L>=x)insert(lc[k],x,val);
    else insert(rc[k],x-L-1,val);
    if(a[rt[k]].sum*alpha>max(a[rt[lc[k]]].sum,a[rt[rc[k]]].sum))
    {
        if(!tmp)return;
        if(lc[k]==tmp)rebuild(lc[k]);else rebuild(rc[k]);
        tmp=0;
    }
    else tmp=k;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&v[i]);
    for(int i=1;i<=n;i++)dfn[i]=i;
    build(root,1,n);
    scanf("%d",&m);
    char ch;int x,y,K;
    while(m--)
    {
        scanf(" %c%d%d",&ch,&x,&y);
        x^=ans;y^=ans;
        if(ch=='Q')scanf("%d",&K),K^=ans,printf("%d\n",ans=solve(x,y,K));
        else if(ch=='M')update(root,x,y);
        else{
            tmp=0;
            insert(root,x-1,y);
            if(tmp)tmp=0,rebuild(root);
        }
    }
}

长链剖分https://www.luogu.org/problemnew/show/P4292

#include<bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int N=2e5+7;
int n,L,R,cnt,tot,hd[N],v[N],nxt[N],w[N],son[N],sv[N],dep[N],dfn[N];
double mid,ans,s[N<<2],val[N],f[N];
void add(int x,int y,int z){v[++tot]=y,nxt[tot]=hd[x],w[tot]=z,hd[x]=tot;}
void dfs1(int u,int fa)
{
    for(int i=hd[u];i;i=nxt[i])
    if(v[i]!=fa)
    {
        dfs1(v[i],u);
        if(dep[v[i]]>=dep[son[u]])son[u]=v[i],sv[u]=w[i];
        if(dep[v[i]]+1>dep[u])dep[u]=dep[v[i]]+1;
    }
}
void dfs2(int u,int fa)
{
    dfn[u]=++cnt;
    if(son[u])dfs2(son[u],u);
    for(int i=hd[u];i;i=nxt[i])if(v[i]!=fa&&v[i]!=son[u])dfs2(v[i],u);
}
void update(int k,double v,int l,int r,int rt)
{
    if(l==r){s[rt]=max(s[rt],v);return;}
    int mid=l+r>>1;
    if(k<=mid)update(k,v,lson);else update(k,v,rson);
    s[rt]=max(s[rt<<1],s[rt<<1|1]);
}
double query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)return s[rt];
    int mid=l+r>>1;double ret=-2e9;
    if(L<=mid)ret=max(ret,query(L,R,lson));
    if(R>mid)ret=max(ret,query(L,R,rson));
    return ret;
}
void dfs(int u,int fa)
{
    int id=dfn[u];
    if(son[u])dfs(son[u],u),val[id]=val[id+1]+sv[u]-mid;
    update(id,f[id]=-val[id],1,n,1);
    if(dep[u]>=L)
    {
        double tmp=query(id+L,id+min(dep[u],R),1,n,1);
        ans=max(ans,tmp+val[id]);
    }
    for(int i=hd[u];i;i=nxt[i])
    if(v[i]!=fa&&v[i]!=son[u])
    {
        int idv=dfn[v[i]];
        dfs(v[i],u);
        for(int j=0;j<=dep[v[i]];j++)
        {
            int l=id+max(0,L-j-1),r=id+min(dep[u],R-j-1);
            double tmp=query(l,r,1,n,1);
            ans=max(ans,tmp+val[idv]+val[id]+f[idv+j]+w[i]-mid);
        }
        for(int j=0;j<=dep[v[i]];++j)
        {
            double tmp=val[idv]+f[idv+j]+w[i]-mid-val[id];
            if(tmp>f[id+j+1])update(id+j+1,f[id+j+1]=tmp,1,n,1);
        }
    }
}
bool check()
{
    for(int i=0;i<(N<<2);i++)s[i]=-2e9;
    ans=-2e9,dfs(1,0);
    return ans>=1e-4;
}
int main()
{
    scanf("%d%d%d",&n,&L,&R);
    for(int i=1,x,y,z;i<n;i++)scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
    dfs1(1,0),dfs2(1,0);
    double l=0,r=1e6;
    while(r-l>1e-4)
    {
        mid=(l+r)/2;
        if(check())l=mid;else r=mid;
    }
    printf("%.3lf",l);
}

fhq-treaphttps://www.luogu.org/problemnew/show/CF702F

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int n,m,root,val[N],cnt[N],tv[N],tc[N],rd[N],ch[N][2];
pair<int,int>a[N];
void pushdown(int x)
{
    if(!x)return;
    int lc=ch[x][0],rc=ch[x][1];
    if(tv[x])
    {
        val[lc]+=tv[x],val[rc]+=tv[x];
        tv[lc]+=tv[x],tv[rc]+=tv[x];
        tv[x]=0;
    }
    if(tc[x])
    {
        cnt[lc]+=tc[x],cnt[rc]+=tc[x];
        tc[lc]+=tc[x],tc[rc]+=tc[x];
        tc[x]=0;
    }
}
void split(int rt,int&x,int&y,int v)
{
    if(!rt){x=y=0;return;}
    pushdown(rt);
    if(val[rt]<v)x=rt,split(ch[rt][1],ch[x][1],y,v);
    else y=rt,split(ch[rt][0],x,ch[y][0],v);
}
int merge(int x,int y)
{
    if(!x||!y)return x+y;
    if(rd[x]<rd[y])
    {
        pushdown(x),ch[x][1]=merge(ch[x][1],y);
        return x;
    }
    else{
        pushdown(y),ch[y][0]=merge(x,ch[y][0]);
        return y;
    }
}
int insert(int x,int y)
{
    int r1=0,r2=0;
    split(x,r1,r2,val[y]);
    r1=merge(r1,y),x=merge(r1,r2);
    return x;
}
int dfs(int x,int y)
{
    if(!x)return y;
    pushdown(x);
    y=dfs(ch[x][0],y),y=dfs(ch[x][1],y);
    ch[x][0]=ch[x][1]=0;
    return insert(y,x);
}
void down(int x)
{
    if(!x)return;
    pushdown(x),down(ch[x][0]),down(ch[x][1]);
}
int main()
{
    scanf("%d",&n);
    for(int i=1,x,y;i<=n;i++)scanf("%d%d",&x,&y),a[i]=make_pair(-y,x);
    sort(a+1,a+n+1);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)scanf("%d",&val[i]),rd[i]=rand(),root=insert(root,i);
    for(int i=1;i<=n;i++)
    {
        int c=a[i].second,r1=0,r2=0,r3=0,r4=0;
        split(root,r1,r2,c);
        val[r2]-=c,tv[r2]-=c;
        cnt[r2]++,tc[r2]++;
        split(r2,r3,r4,c-1);
        r1=dfs(r3,r1),root=merge(r1,r4);
    }
    down(root);
    for(int i=1;i<=m;i++)printf("%d ",cnt[i]);
}

笛卡尔树https://www.luogu.org/problemnew/show/SP3734

#include<bits/stdc++.h>
using namespace std;
const int N=525,M=1e6+7,mod=1e9+7;
int n,m,top,f[N][N],g[N],fac[M],inv[M],v[N],st[N],fa[N],ch[N][2];
int C(int a,int b){return a<b?0:1ll*fac[a]*inv[b]%mod*inv[a-b]%mod;}
int dfs(int x)
{
    int a=1,b=v[x]-v[fa[x]],y,s;
    f[x][0]=1;
    for(int i=0;i<2;i++)
    if(ch[x][i])
    {
        y=ch[x][i],s=dfs(y);
        memset(g,0,sizeof g);
        for(int j=0;j<=a;j++)
        for(int k=0;k<=s&&j+k<=m;k++)
        g[j+k]=(g[j+k]+1ll*f[x][j]*f[y][k])%mod;
        a+=s;
        for(int j=0;j<=a;j++)f[x][j]=g[j];
    }
    for(int i=min(m,a);~i;i--)
    {
        s=0;
        for(int j=0;j<=i;j++)s=(s+1ll*f[x][i-j]*fac[j]%mod*C(a-i+j,j)%mod*C(b,j))%mod;
        f[x][i]=s;
    }
    return a;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&v[i]);
    fac[0]=1;for(int i=1;i<M;i++)fac[i]=1ll*fac[i-1]*i%mod;
    inv[0]=inv[1]=1;for(int i=2;i<M;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    for(int i=2;i<M;i++)inv[i]=1ll*inv[i-1]*inv[i]%mod;
    for(int i=1;i<=n;i++)
    {
        while(top&&v[st[top]]>v[i])
        {
            int x=st[top--];
            if(top&&v[st[top]]>v[i])ch[st[top]][1]=x,fa[x]=st[top];
            else ch[i][0]=x,fa[x]=i;
        }
        st[++top]=i;
    }
    while(top>1)ch[st[top-1]][1]=st[top],fa[st[top]]=st[top-1],top--;
    dfs(st[1]);
    printf("%d",f[st[1]][m]);
}

树套树https://www.lydsy.com/JudgeOnline/problem.php?id=3489

#include<bits/stdc++.h>
#define lson l,mid,ch[rt][0]
#define rson mid+1,r,ch[rt][1]
using namespace std;
const int N=1e5+7,M=4e7+7;
typedef long long ll;
struct node{int x,y,z,v;};
int n,m,tot,ans,a[N],pre[N],nxt[N],lst[N],rt[N],ch[M][2],v[M];
node p[N];
bool operator<(node x,node y){return x.x<y.x;}
void change(int prt,int l,int r,int&rt,node c)
{
    rt=++tot;
    memcpy(ch[rt],ch[prt],sizeof ch[rt]);
    v[rt]=max(v[prt],c.v);
    if(l==r)return;
    int mid=l+r>>1;
    if(c.z<=mid)change(ch[prt][0],lson,c);
    else change(ch[prt][1],rson,c);
}
void modify(int prt,int l,int r,int&rt,node c)
{
    rt=++tot;
    memcpy(ch[rt],ch[prt],sizeof ch[rt]);
    change(v[prt],1,n+2,v[rt],c);
    if(l==r)return;
    int mid=l+r>>1;
    if(c.y<=mid)modify(ch[prt][0],lson,c);
    else modify(ch[prt][1],rson,c);
}
int ask(int L,int R,int l,int r,int rt)
{
    if(!rt)return 0;
    if(L<=l&&r<=R)return v[rt];
    int mid=l+r>>1,ret=0;
    if(L<=mid)ret=max(ret,ask(L,R,lson));
    if(R>mid)ret=max(ret,ask(L,R,rson));
    return ret;
}
int query(int L,int R,int l,int r,int rt,int ql,int qr)
{
    if(!rt)return 0;
    if(L<=l&&r<=R)return ask(ql,qr,1,n+2,v[rt]);
    int mid=l+r>>1,ret=0;
    if(L<=mid)ret=max(ret,query(L,R,lson,ql,qr));
    if(R>mid)ret=max(ret,query(L,R,rson,ql,qr));
    return ret;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)lst[i]=1;
    for(int i=2;i<=n+1;i++)scanf("%d",&a[i]),nxt[lst[a[i]]]=i,pre[i]=lst[a[i]],lst[a[i]]=i;
    for(int i=1;i<=n;i++)nxt[lst[i]]=n+2;
    for(int i=2;i<=n+1;i++)p[i-1]=(node){pre[i],nxt[i],i,a[i]};
    sort(p+1,p+n+1);
    for(int i=1,pos=1;i<=n+2;i++)
    {
        rt[i]=rt[i-1];
        while(p[pos].x==i&&pos<=n)modify(rt[i],1,n+2,rt[i],p[pos++]);
    }
    while(m--)
    {
        int x,y,l,r;
        scanf("%d%d",&x,&y);
        x=(x+ans)%n+2,y=(y+ans)%n+2,l=min(x,y),r=max(x,y);
        printf("%d\n",ans=query(r+1,n+2,1,n+2,rt[l-1],l,r));
    }
}

LCThttps://www.luogu.org/problemnew/show/P3203

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=2e5+7;
int n,fa[N],ch[N][2],nxt[N],st[N],sz[N],rev[N];
bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void pushup(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;}
void pushdown(int x)
{
    int l=ch[x][0],r=ch[x][1];
    if(rev[x])rev[x]^=1,rev[l]^=1,rev[r]^=1,swap(ch[x][0],ch[x][1]);
}
void rotate(int x)
{
    int y=fa[x],z=fa[fa[x]],l;
    l=(ch[y][1]==x);
    if(!isroot(y))
    {
        if(ch[z][0]==y)ch[z][0]=x;
        else ch[z][1]=x;
    }
    fa[x]=z,fa[y]=x;
    fa[ch[x][l^1]]=y;
    ch[y][l]=ch[x][l^1],ch[x][l^1]=y;
    pushup(y),pushup(x);
}
void splay(int x)
{
    st[1]=x;
    int top=1;
    for(int i=x;!isroot(i);i=fa[i])st[++top]=fa[i];
    for(int i=top;i;i--)pushdown(st[i]);
    while(!isroot(x))
    {
        int y=fa[x],z=fa[fa[x]];
        if(!isroot(y))
        {
            if((ch[y][0]==x)^(ch[z][0]==y))rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
}
void access(int x)
{
    int t=0;
    while(x)splay(x),ch[x][1]=t,t=x,x=fa[x];
}
void reverse(int x){access(x),splay(x),rev[x]^=1;}
void link(int x,int y){reverse(x),fa[x]=y,splay(x);}
void cut(int x,int y){reverse(x),access(y),splay(y),ch[y][0]=fa[x]=0;}
int main()
{
    scanf("%d",&n);
    int op,x,y,Q;
    for(int i=1;i<=n;i++)scanf("%d",&x),fa[i]=min(x+i,n+1),sz[i]=1,nxt[i]=fa[i];
    sz[n+1]=1;
    scanf("%d",&Q);
    while(Q--)
    {
        scanf("%d%d",&op,&x);
        x++;
        if(op==1)reverse(n+1),access(x),splay(x),printf("%d\n",sz[ch[x][0]]);
        else scanf("%d",&y),cut(x,nxt[x]),link(x,min(x+y,n+1)),nxt[x]=min(x+y,n+1);
    }
}

KD-Treehttps://www.lydsy.com/JudgeOnline/problem.php?id=2850

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=50010,inf=2e9;
struct Node{int mx[2],mn[2],d[2],lc,rc,v;ll s;}t[maxn],x;
int D,n,m,rt,a,b,c;
bool operator<(Node a,Node b){return a.d[D]<b.d[D];}
void update(int k)
{
    t[k].s=t[t[k].lc].s+t[t[k].rc].s+t[k].v;
    for(int i=0;i<2;i++)
    {
        t[k].mn[i]=min(min(t[t[k].lc].mn[i],t[t[k].rc].mn[i]),t[k].d[i]);
        t[k].mx[i]=max(max(t[t[k].lc].mx[i],t[t[k].rc].mx[i]),t[k].d[i]);
    }
}
void build(int&k,int l,int r,int cur)
{
    k=0;
    if(l>r)return;
    D=cur;
    int mid=(l+r)/2;
    nth_element(t+l,t+mid,t+r+1);
    k=mid;
    build(t[k].lc,l,mid-1,cur^1);
    build(t[k].rc,mid+1,r,cur^1);
    update(k);
}
bool inner(int x,int y){return 1ll*a*x+1ll*b*y<c;}
int check(int k)
{
    int cnt=0;
    if(inner(t[k].mn[0],t[k].mn[1]))cnt++;
    if(inner(t[k].mn[0],t[k].mx[1]))cnt++;
    if(inner(t[k].mx[0],t[k].mn[1]))cnt++;
    if(inner(t[k].mx[0],t[k].mx[1]))cnt++;
    if(!cnt)return 0;
    if(cnt==4)return 1;
    return -1;
}
ll query(int k)
{
    if(!k)return 0;
    int f=check(k);
    if(!f)return 0;
    if(f==1)return t[k].s;
    return query(t[k].lc)+query(t[k].rc)+t[k].v*inner(t[k].d[0],t[k].d[1]);
}
int main()
{
    scanf("%d%d",&n,&m);
    t[0].mn[0]=t[0].mn[1]=1e9;
    t[0].mx[0]=t[0].mx[1]=-1e9;
    for(int i=1;i<=n;i++)scanf("%d%d%d",&t[i].d[0],&t[i].d[1],&t[i].v);
    build(rt,1,n,0);
    while(m--)scanf("%d%d%d",&a,&b,&c),printf("%lld\n",query(rt));
}

线段树优化建图https://www.luogu.org/problemnew/show/CF786B

#include<bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
typedef long long ll;
using namespace std;
typedef pair<int,int>pii;
const int N=1e5+7;
struct node{int u;ll d;};
int n,m,S,tot,id[2][N<<2],vis[N*5];
ll d[N*5];
vector<pii>G[N*5];
vector<int>vec;
bool operator<(node a,node b){return a.d>b.d;}
priority_queue<node>q;
void adde(int u,int v,int w){G[u].push_back(pii(v,w));}
void build(int l,int r,int rt,int k)
{
    id[k][rt]=++tot;
    if(l==r)
    {
        if(!k)adde(id[k][rt],l,0);else adde(l,id[k][rt],0);
        return;
    }
    int mid=l+r>>1;
    build(lson,k),build(rson,k);
    if(!k)adde(id[k][rt],id[k][rt<<1],0),adde(id[k][rt],id[k][rt<<1|1],0);
    else adde(id[k][rt<<1],id[k][rt],0),adde(id[k][rt<<1|1],id[k][rt],0);
}
void query(int L,int R,int k,int l,int r,int rt)
{
    if(L<=l&&r<=R){vec.push_back(id[k][rt]);return;}
    int mid=l+r>>1;
    if(L<=mid)query(L,R,k,lson);
    if(R>mid)query(L,R,k,rson);
}
void dijkstra(int S)
{
    for(int i=1;i<=5*n;i++)d[i]=1e18,vis[i]=0;
    q.push((node){S,0}),d[S]=0;
    while(!q.empty())
    {
        int u=q.top().u;q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=0;i<G[u].size();i++)
        {
            int v=G[u][i].first,w=G[u][i].second;
            if(d[v]>d[u]+w)d[v]=d[u]+w,q.push((node){v,d[v]});
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&S);
    tot=n;
    build(1,n,1,0),build(1,n,1,1);
    while(m--)
    {
        int op,x,l,r,w;scanf("%d%d%d",&op,&x,&l);
        if(op==1)scanf("%d",&w),adde(x,l,w);
        else if(op==2)
        {
            vec.clear();
            scanf("%d%d",&r,&w);
            query(l,r,0,1,n,1);
            for(int i=0;i<vec.size();i++)adde(x,vec[i],w);
        }
        else{
            vec.clear();
            scanf("%d%d",&r,&w);
            query(l,r,1,1,n,1);
            for(int i=0;i<vec.size();i++)adde(vec[i],x,w);
        }
    }
    dijkstra(S);
    for(int i=1;i<=n;i++)if(d[i]==1e18)printf("-1 ");else printf("%lld ",d[i]);
}

暂时没了。

posted @ 2019-06-17 11:07  hfctf0210  阅读(231)  评论(0)    收藏  举报